Among many interesting features that PostgreSQL has to offer, one of the most exciting ones is the ability to write extensions. It is possible to easily extend Postgres functionality by creating an extension module for it. Another important aspect is that you can write it in almost any language.
Table of Contents
Before you get all riled up and start typing the code you have always wanted, take a deep breath! Postgres already comes with many useful extensions. These are the extensions that make its contrib module — check out the official list. You may use any of these extensions by simply installing them and then using CREATE EXTENSION extension_name on your Postgres client.
1 2 3 4 5 6 7 8 9 10 |
postgres=# \h CREATE EXTENSION Command: CREATE EXTENSION Description: install an extension Syntax: CREATE EXTENSION [ IF NOT EXISTS ] extension_name [ WITH ] [ SCHEMA schema_name ] [ VERSION version ] [ CASCADE ] URL: https://www.postgresql.org/docs/17/sql-createextension.html |
If these extensions do not cover what you are looking for, then I came across this quite extensive list of available extensions. If nothing here could solve your problem, then you are in luck, because now you have a fair chance of writing an extension yourself.
This blog will cover the basic process to write a working Postgres extension. Let’s understand this process with a running example of creating an extension which converts a given text-to-title format. Let’s call this extension pg_make_title
Writing a Makefile
If this is the first time you are going to write the Makefile, don’t worry, this is a simple one. It should look something like this:
1 2 3 4 5 6 |
PGFILEDESC = "Extension to convert a text to tile format" EXTENSION = pg_make_title DATA = pg_make_title--1.0.sql PG_CONFIG = pg_config PGXS := $(shell $(PG_CONFIG) --pgxs) include $(PGXS) |
PGXS is the most interesting thing here. It allows you to install the extension on the already installed PostgreSQL server. All the environment variables, etc. it requires to set up the extension can then be easily accessed using pg_config.
This is an important file that needs to be written. This is how the server knows the basic stuff about the extension, like version, etc. It is named as extension_name.control and would look something like this:
1 2 3 4 |
comment = 'convert text to title format' default_version = '1.0' module_pathname = '$libdir/pg_make_title relocatable = true |
This is the script which will install your extension. This is the code which will run when you call CREATE EXTENSION <MY_AWESOME_EXTENSION>; Any view, function, etc. that needs to be created for the working of the extension comes here. One important line to add at the beginning of the file:
1 2 |
-- complain if script is sourced in psql, rather than via CREATE EXTENSION \echo Use "CREATE EXTENSION pg_make_title" to load this file. \quit |
Then comes the definition of the functions to be used:
1 2 3 4 5 6 7 8 9 10 11 12 |
/* Now define */ CREATE FUNCTION convert_to_title(inp text) RETURNS text LANGUAGE plpgsql IMMUTABLE STRICT AS $$ DECLARE ret text; BEGIN ret := (SELECT INITCAP(inp)); RETURN(ret); END; $$; |
Keep the name of the file something like pg_make_title–1.0.sql — the version
the number after the extension name should be the same as the one given in the default_version field in the control file.
Now, let’s try using this extension. For this we need to go through following steps:
1 |
SELECT convert_to_title('create your first extension'); |
This will give you,
1 2 3 4 |
convert_to_title ----------------------------- Create Your First Extension (1 row) |
Here comes the interesting stuff. If you are writing an extension which calls some C functions or some complex SQL queries, then you write them here. These functions can be called from extension.sql
For our running example, let’s go one step further and write this function in C language. So now, our pg_make_title.c would look something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/*-------------------------------------------------- * pg_make_title.c * ------------------------------------------------- */ #include "postgres.h" #include "utils/builtins.h" #include "c.h" PG_MODULE_MAGIC; PG_FUNCTION_INFO_V1(convert_to_title); Datum convert_to_title(PG_FUNCTION_ARGS) { char *input = text_to_cstring(PG_GETARG_TEXT_PP(0)); … PG_RETURN_CSTRING(input); } |
Here PG_MODULE_MAGIC, is actually a magic block provided by PostgreSQL infrastructure to check for any incompatibility with respect to the version downloaded, etc.
Next, PG_FUNCTION_INFO_V1(convert_to_title), is required for every function that is to be called from the Postgresql interface.
At the end, Datum convert_to_title(PG_FUNCTION_ARGS) says that this function can take arguments and returns datum. Here, PG_FUNCTION_ARGS means that it takes any type and number of arguments.
After making these changes to the C source file, we also need to add …
1 |
MODULES = pg_make_title |
… in the Makefile.
Do not forget to modify pg_make_title–1.0.sql like this:
1 2 3 4 |
/* Now define */ CREATE FUNCTION convert_to_title(inp text) RETURNS text AS 'MODULE_PATHNAME' LANGUAGE C STRICT VOLATILE; |
Now it knows that the function definition is in C and not the SQL function as before.
Running make install in the repo will install the extension and will use the code from the C source file.
It is a good practice to provide a testing mechanism for your extension with your extension. PostgreSQL helps here by providing the regression suite. For this you need to create a SQL directory inside which resides a SQL file with all the test cases. For our example, it may look something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
CREATE EXTENSION pg_make_title version '1.0'; --1. Check normal string SELECT convert_to_title('create your first extension'); --2. Check string starting with space SELECT convert_to_title(' create your first extension'); --3. Check string starting with number SELECT convert_to_title('1 create your first extension'); --4. Check empty string SELECT convert_to_title(''); --5. Check multiple strings SELECT convert_to_title('create your first extension','create your second extension'); |
Next, add this line to your Makefile
1 |
REGRESS = pg_make_title |
Now run make installcheck to create an .out file in the results subdirectory. This is the output of running the tests you wrote in the test file. Once you verify all the output is as you expect it to be, create a subdirectory expected here and move this .out file there. Now every time make installcheck is issued, the results are checked against this file in the expected subdirectory.
Well, who doesn’t value the importance of a good README file? Particularly, when you have a super awesome extension doing the super awesome stuff that didn’t cross people’s minds before. Make it all shiny with a good README file.
You need to load content from reCAPTCHA to submit the form. Please note that doing so will share data with third-party providers.
More InformationYou are currently viewing a placeholder content from Facebook. To access the actual content, click the button below. Please note that doing so will share data with third-party providers.
More InformationYou are currently viewing a placeholder content from X. To access the actual content, click the button below. Please note that doing so will share data with third-party providers.
More Information
Leave a Reply