> For the complete documentation index, see [llms.txt](https://mariadb.com/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://mariadb.com/docs/server/reference/product-development/plugin-development/development-writing-plugins-for-mariadb.md).

# Writing Plugins for MariaDB

A comprehensive guide on the basic structure and necessary components for creating a new plugin from scratch.

{% hint style="info" %}
This page contains background information for MariaDB developers.
{% endhint %}

## About

Generally speaking, writing plugins for MariaDB is very similar to writing plugins for MySQL.

## Authentication Plugins

See [Pluggable Authentication](/docs/server/reference/plugins/authentication-plugins/pluggable-authentication-overview.md).

## Storage Engine Plugins

Storage engines can extend `CREATE TABLE` syntax with optional index, field, and table attribute clauses. See [Extending CREATE TABLE](/docs/server/reference/product-development/plugin-development/storage-engines-storage-engine-development/engine-defined-new-tablefieldindex-attributes.md) for more information. See also [Storage Engine Development](/docs/server/reference/product-development/plugin-development/storage-engines-storage-engine-development.md).

## Information Schema Plugins

Information Schema plugins can have their own [FLUSH](/docs/server/reference/sql-statements/administrative-sql-statements/flush-commands/flush.md) and [SHOW](/docs/server/reference/sql-statements/administrative-sql-statements/show.md) statements. See [FLUSH and SHOW for Information Schema plugins](/docs/server/reference/product-development/plugin-development/information-schema-plugins-show-and-flush-statements.md).

## Encryption Plugins

[Encryption plugins](/docs/server/reference/product-development/plugin-development/encryption-plugin-api.md) in MariaDB are used for the [data at rest encryption](/docs/server/security/encryption/data-at-rest-encryption.md) feature. They are responsible for both key management and for the actual encryption and decryption of data.

## Function Plugins

Function plugins add new SQL functions to MariaDB. Unlike the old [UDF API](/docs/server/server-usage/user-defined-functions.md), a function plugin supplies a complete `Item` subclass — the same representation the server uses for its own native functions — so it defines its own return type, argument handling, and evaluation, and can do almost anything a built-in function can.

Several functions that look built-in are implemented this way, including `UUID()`, `UUID_V4()`, `UUID_V7()` and `SYS_GUID()`, the `INET_ATON()`, `INET6_NTOA()` and `IS_IPV4()` family, and `CURSOR_REF_COUNT()`.

### The Plugin Descriptor

The API is declared in `include/mysql/plugin_function.h`. The type-specific descriptor for a function plugin is a `Plugin_function` object wrapping a pointer to a `Create_func` builder:

```c
static Plugin_function
  plugin_descriptor_function_sysconst_test(&Create_func_sysconst_test::s_singleton);
```

The builder is what the parser calls to construct the function's `Item` each time the function appears in a statement.

### Function Names and Precedence

The plugin name **is** the SQL function name. When the parser meets a function name it does not recognize, it looks for a plugin of type `FUNCTION` registered under exactly that name. A plugin therefore provides exactly one SQL function; to add several functions, declare several plugins.

Built-in functions take precedence. The server searches its native function registry first and consults function plugins only when the name is not already taken, so a function plugin cannot override or replace a built-in function.

### Declaring the Plugin

Use the ordinary [plugin declaration](#plugin-declaration-structure), with `MariaDB_FUNCTION_PLUGIN` as the type and the `Plugin_function` descriptor as the info pointer:

```c
maria_declare_plugin(sysconst_test)
{
  MariaDB_FUNCTION_PLUGIN,                   // the plugin type
  &plugin_descriptor_function_sysconst_test, // type-specific descriptor
  "sysconst_test",                           // plugin name, and the SQL function name
  "MariaDB Corporation",                     // plugin author
  "Function SYSCONST_TEST()",                // the plugin description
  PLUGIN_LICENSE_GPL,                        // the plugin license
  0,                                         // pointer to plugin initialization function
  0,                                         // pointer to plugin deinitialization function
  0x0100,                                    // numeric version 0xAABB means AA.BB version
  NULL,                                      // status variables
  NULL,                                      // system variables
  "1.0",                                     // string version representation
  MariaDB_PLUGIN_MATURITY_EXPERIMENTAL       // maturity
}
maria_declare_plugin_end;
```

A complete worked example, covering both a function taking no arguments and functions taking arguments, is in the source tree at `plugin/func_test/plugin.cc`. It is built only as a test component, so it is not present in a normal server installation.

### Viewing Function Plugins

Function plugins appear in [SHOW PLUGINS](/docs/server/reference/sql-statements/administrative-sql-statements/show/show-plugins.md) with a `Type` of `FUNCTION`, and the functions they provide are listed in the [Information Schema SQL\_FUNCTIONS table](/docs/server/reference/system-tables/information-schema/information-schema-tables/information-schema-sql_functions-table.md) alongside built-in functions.

Function plugins are initialized early in server startup, before storage engine plugins.

## Building and Packaging a Plugin

{% hint style="info" %}
Building a plugin with only the MariaDB development package, without the server source tree, requires MariaDB 11.4.14, 11.8.10, 12.3.4, 13.1.2, 13.2.1, or later ([MDEV-40608](https://jira.mariadb.org/browse/MDEV-40608)).
{% endhint %}

To build a plugin, install the MariaDB development package. On RPM-based distributions:

```bash
dnf install MariaDB-devel
```

On Debian and Ubuntu:

```bash
apt install libmariadb-dev
```

Then create a `CMakeLists.txt` file. For a simple plugin, a few lines are enough:

```cmake
cmake_minimum_required(VERSION 3.12)
find_package(mariadb-plugin REQUIRED)
MARIADB_ADD_PLUGIN(exampledb example.cc STORAGE_ENGINE
                 AUTHOR "John Smith" VERSION 0.1
                 DESCRIPTION "Example of plugin interface")
include(CPack)
```

With this file, you can do the following:

* Configure the build: `cmake .`. To build packages, add `-DRPM=1` or `-DDEB=1`, depending on the kind of package you need.
* Compile the plugin: `cmake --build .`
* Install the plugin: `cmake --build . --target install`
* Create a package: `cmake --build . --target package`

If MariaDB was installed from a `.tar.gz` or `.zip` archive, the development files are not in a standard location. Pass the MariaDB base directory when you configure the build:

```bash
cmake . -DCMAKE_PREFIX_PATH=/path/to/mariadb/basedir
```

## Plugin Declaration Structure

The MariaDB plugin declaration differs from the MySQL plugin declaration in the following ways:

1. it has no useless 'reserved' field (the very last field in the MySQL plugin declaration)
2. it has a 'maturity' declaration
3. it has a field for a text representation of the version field

MariaDB can load plugins that only have the MySQL plugin declaration but both `PLUGIN_MATURITY` and `PLUGIN_AUTH_VERSION` will show up as 'Unknown' in the [INFORMATION\_SCHEMA.PLUGINS table](/docs/server/reference/system-tables/information-schema/information-schema-tables/plugins-table-information-schema.md).

For compiled-in (not dynamically loaded) plugins, the presence of the MariaDB plugin declaration is mandatory.

### Example Plugin Declaration

The MariaDB plugin declaration looks like this:

```c
/* MariaDB plugin declaration */
maria_declare_plugin(example)
{
   MYSQL_STORAGE_ENGINE_PLUGIN, /* the plugin type (see include/mysql/plugin.h) */
   &example_storage_engine_info, /* pointer to type-specific plugin descriptor   */
   PLUGIN_NAME, /* plugin name */
   PLUGIN_AUTHOR,  /* plugin author */
   PLUGIN_DESCRIPTION, /* the plugin description */
   PLUGIN_LICENSE, /* the plugin license (see include/mysql/plugin.h) */
   example_init_func,   /* Pointer to plugin initialization function */
   example_deinit_func,  /* Pointer to plugin deinitialization function */
   PLUGIN_HEX_VERSION, /* Numeric version 0xAABB means AA.BB version */
   example_status_variables,  /* Status variables */
   example_system_variables,  /* System variables */
   PLUGIN_VERSION,  /* String version representation */
   MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* Maturity (see include/mysql/plugin.h)*/
}
maria_declare_plugin_end;
```

The build takes the values of `PLUGIN_NAME`, `PLUGIN_AUTHOR`, `PLUGIN_DESCRIPTION`, `PLUGIN_VERSION`, and `PLUGIN_HEX_VERSION` from the `MARIADB_ADD_PLUGIN()` call in `CMakeLists.txt`, and sets `PLUGIN_LICENSE` to `PLUGIN_LICENSE_GPL`. You can also specify the values explicitly, as in the `sysconst_test` example above. This is particularly useful if the plugin binary contains several plugins.

## Maturity Guidelines For Plugins

### Plugin Maturity At a Glance

```mermaid
stateDiagram-v2
    accTitle: Plugin maturity stages
    accDescr {
        A state diagram with three top-level states: Experimental, Release
        Candidate and General Availability. Experimental leads to Release
        Candidate, which leads to General Availability. Experimental is a box that
        contains the states Alpha and Beta, with its own start and end markers.
        Inside it, the start marker leads to Alpha, to Beta and to the end marker.
        Alpha leads to Beta, and Beta leads to the end marker.
    }
    state "Release Candidate" as RC
    state "General Availability" as GA
    state "Experimental" as Exp {
      [*] --> Alpha
      [*] --> Beta
      Alpha --> Beta
      Beta --> [*]
      [*] --> [*]
    }
    Exp --> RC
    RC --> GA
```

### Plugin Maturity Guidelines

{% hint style="info" %}
New features or sufficiently big code changes to a plugin should lead to:

* an increase of the plugin version

* knocking the maturity level down.
  {% endhint %}

* First a plugin is Alpha

* After at least 1.5 months (or more, in 3 month increments, until the quality is deemed acceptable) it becomes Gamma. Meanwhile it can transition through Beta as the maintainer wants (e,g. it can start directly from beta)

* After at least 3 more months (or more, in 3 month increments — depending on the bug inflow) it becomes Stable

If a plugin must be statically compiled into the server, it is a subject to an additional limitation — its maturity cannot be lower than the server's.

## Beta Plugins In GA Releases

If a plugin contribution is added directly at beta maturity to a GA release series, it will not be removed from that release series. However, we reserve the right to exclude a plugin from future release series if it is unmaintained (for example, if it stops receiving bug fixes).

<sub>*This page is licensed: CC BY-SA / Gnu FDL*</sub>

{% @marketo/form formId="4316" %}
