You can write plugins in C or C++ (or another language that can use C calling conventions). Plugins are loaded and unloaded dynamically, so your operating system must support dynamic loading and you must have compiled mysqld dynamically (not statically).
        A plugin contains code that becomes part of the running server,
        so when you write a plugin, you are bound by any and all
        constraints that otherwise apply to writing server code. For
        example, you may have problems if you attempt to use functions
        from the libstdc++ library. These constraints
        may change in future versions of the server, so it is possible
        that server upgrades will require revisions to plugins that were
        originally written for older servers. For information about
        these constraints, see Section 2.10.2, “Typical configure Options”, and
        Section 2.10.4, “Dealing with Problems Compiling MySQL”.
      
        This section provides a step-by-step guide to creating a plugin
        library. It shows how to develop a library that contains a
        full-text parsing plugin named simple_parser.
        This plugin performs parsing based on simpler rules than those
        used by the MySQL built-in full-text parser: Words are nonempty
        runs of whitespace characters. For example plugin source code,
        see the plugin/fulltext directory of a
        MySQL source distribution.
      
Each plugin library has the following contents:
A plugin library descriptor that indicates the version number of the general plugin API that the library uses and that contains a general declaration for each plugin in the library.
Each general plugin descriptor contains information that is common to all types of plugin: A value that indicates the plugin type; the plugin name, author, description, and license type; and pointers to the initialization and deinitialization functions that the server invokes when it loads and unloads the plugin.
The general plugin descriptor also contains a pointer to a type-specific plugin descriptor. The structure of these descriptors can vary from one plugin type to another, because each type of plugin can have its own API. A plugin descriptor contains a type-specific API version number and pointers to the functions that are needed to implement that plugin type. For example, a full-text parser plugin has initialization and deinitialization functions, and a main parsing function. The server invokes these functions when it uses the plugin to parse text.
The plugin library contains the interface functions that are referenced by the general and type-specific descriptors for each plugin in the library.
        The easiest way to follow the instructions in this section is to
        use the source code in the plugin/fulltext
        directory of a MySQL source distribution. The instructions
        assume that you make a copy of that directory and use it to
        build the plugin library. To make a copy of the directory, use
        the following commands, which assume that the MySQL source tree
        is in a directory named
        mysql-5.5 under your current
        directory:
      
shell>mkdir fulltext_pluginshell>cp mysql-5.5/plugin/fulltext/* fulltext_plugin
        If you are copying files from a Bazaar source tree,
        cp will display an error message about the
        SCCS directory, which you can ignore.
      
After copying the source files, use the following procedure to create a plugin library:
            Change location into the
            fulltext_plugin directory:
          
shell> cd fulltext_plugin
            The plugin source file should include the header files that
            the plugin library needs. The plugin.h
            file is required, and the library might require other files
            as well. For example:
          
#include <stdlib.h> #include <ctype.h> #include <mysql/plugin.h>
Set up the plugin library file descriptor.
Every plugin library must include a library descriptor that must define two symbols:
                _mysql_plugin_interface_version_
                specifies the version number of the general plugin
                framework. This is given by the
                MYSQL_PLUGIN_INTERFACE_VERSION
                symbol, which is defined in the
                plugin.h file.
              
                _mysql_plugin_declarations_ defines
                an array of plugin declarations, terminated by a
                declaration with all members set to 0. Each declaration
                is an instance of the st_mysql_plugin
                structure (also defined in
                plugin.h). There must be one of
                these for each plugin in the library.
              
If the server does not find these two symbols in a library, it does not accept it as a legal plugin library and rejects it with an error. This prevents use of a library for plugin purposes unless it was built specifically as a plugin library.
            The standard (and most convenient) way to define the two
            required symbols is by using the
            mysql_declare_plugin and
            mysql_declare_plugin_end macros from the
            plugin.h file:
          
mysql_declare_plugin
 ... one or more plugin declarations here ...
mysql_declare_plugin_end;
            For example, the library descriptor for a library that
            contains a single plugin named
            simple_parser looks like this:
          
mysql_declare_plugin
{
  MYSQL_FTPARSER_PLUGIN,      /* type                            */
  &simple_parser_descriptor,  /* descriptor                      */
  "simple_parser",            /* name                            */
  "Oracle Corporation",       /* author                          */
  "Simple Full-Text Parser",  /* description                     */
  PLUGIN_LICENSE_GPL,         /* plugin license                  */
  simple_parser_plugin_init,  /* init function (when loaded)     */
  simple_parser_plugin_deinit,/* deinit function (when unloaded) */
  0x0001,                     /* version                         */
  simple_status               /* status variables                */
}
mysql_declare_plugin_end;
            For a full-text parser plugin, the type must be
            MYSQL_FTPARSER_PLUGIN. This is the value
            that identifies the plugin as being legal for use in a
            WITH PARSER clause when creating a
            FULLTEXT index. (No other plugin type is
            legal for this clause.)
          
            The mysql_declare_plugin and
            mysql_declare_plugin_end macros are
            defined in plugin.h like this:
          
#ifndef MYSQL_DYNAMIC_PLUGIN
#define __MYSQL_DECLARE_PLUGIN(NAME, VERSION, PSIZE, DECLS)           \
int VERSION= MYSQL_PLUGIN_INTERFACE_VERSION;                          \
int PSIZE= sizeof(struct st_mysql_plugin);                            \
struct st_mysql_plugin DECLS[]= {
#else
#define __MYSQL_DECLARE_PLUGIN(NAME, VERSION, PSIZE, DECLS)           \
int _mysql_plugin_interface_version_= MYSQL_PLUGIN_INTERFACE_VERSION; \
int _mysql_sizeof_struct_st_plugin_= sizeof(struct st_mysql_plugin);  \
struct st_mysql_plugin _mysql_plugin_declarations_[]= {
#endif
#define mysql_declare_plugin(NAME) \
__MYSQL_DECLARE_PLUGIN(NAME, \
                 builtin_ ## NAME ## _plugin_interface_version, \
                 builtin_ ## NAME ## _sizeof_struct_st_plugin, \
                 builtin_ ## NAME ## _plugin)
#define mysql_declare_plugin_end ,{0,0,0,0,0,0,0,0,0}}
              Those declarations define the
              _mysql_plugin_interface_version_ symbol
              only if the MYSQL_DYNAMIC_PLUGIN symbol
              is defined. This means that you'll need to provide
              -DMYSQL_DYNAMIC_PLUGIN as part of the
              compilation command so that the plugin is built as a
              shared library.
            
            When the macros are used as just shown, they expand to the
            following code, which defines both of the required symbols
            (_mysql_plugin_interface_version_ and
            _mysql_plugin_declarations_):
          
int _mysql_plugin_interface_version_= MYSQL_PLUGIN_INTERFACE_VERSION;
struct st_mysql_plugin _mysql_plugin_declarations_[]= {
{
  MYSQL_FTPARSER_PLUGIN,      /* type                            */
  &simple_parser_descriptor,  /* descriptor                      */
  "simple_parser",            /* name                            */
  "Oracle Corporation",       /* author                          */
  "Simple Full-Text Parser",  /* description                     */
  PLUGIN_LICENSE_GPL,         /* plugin license                  */
  simple_parser_plugin_init,  /* init function (when loaded)     */
  simple_parser_plugin_deinit,/* deinit function (when unloaded) */
  0x0001,                     /* version                         */
  simple_status               /* status variables                */
}
  ,{0,0,0,0,0,0,00,0}
};
            The preceding example declares a single plugin in the
            library descriptor, but it is possible to declare multiple
            plugins. List the declarations one after the other between
            mysql_declare_plugin and
            mysql_declare_plugin_end, separated by
            commas.
          
            MySQL plugins can be written in C or C++ (or another
            language that can use C calling conventions). If you write a
            C++ plugin, one C++ feature that you should not use is
            nonconstant variables to initialize global structures.
            Members of structures such as the
            st_mysql_plugin structure should be
            initialized only with constant variables. The
            simple_parser descriptor shown earlier is
            allowable in a C++ plugin because it satisfies that
            requirement:
          
mysql_declare_plugin
{
  MYSQL_FTPARSER_PLUGIN,      /* type                            */
  &simple_parser_descriptor,  /* descriptor                      */
  "simple_parser",            /* name                            */
  "Oracle Corporation",       /* author                          */
  "Simple Full-Text Parser",  /* description                     */
  PLUGIN_LICENSE_GPL,         /* plugin license                  */
  simple_parser_plugin_init,  /* init function (when loaded)     */
  simple_parser_plugin_deinit,/* deinit function (when unloaded) */
  0x0001,                     /* version                         */
  simple_status               /* status variables                */
}
mysql_declare_plugin_end;
Here is another valid way to write the descriptor. It uses constant variables to indicate the plugin name, author, and description:
const char *simple_parser_name = "simple_parser";
const char *simple_parser_author = "Oracle Corporation";
const char *simple_parser_description = "Simple Full-Text Parser";
mysql_declare_plugin
{
  MYSQL_FTPARSER_PLUGIN,      /* type                            */
  &simple_parser_descriptor,  /* descriptor                      */
  simple_parser_name,         /* name                            */
  simple_parser_author,       /* author                          */
  simple_parser_description,  /* description                     */
  PLUGIN_LICENSE_GPL,         /* plugin license                  */
  simple_parser_plugin_init,  /* init function (when loaded)     */
  simple_parser_plugin_deinit,/* deinit function (when unloaded) */
  0x0001,                     /* version                         */
  simple_status               /* status variables                */
}
mysql_declare_plugin_end;
However, the following descriptor is invalid. It uses structure members to indicate the plugin name, author, and description, but structures are not considered constant initializers in C++:
typedef struct
{
  const char *name;
  const char *author;
  const char *description;
} plugin_info;
plugin_info parser_info = {
  "simple_parser",
  "Oracle Corporation",
  "Simple Full-Text Parser"
};
mysql_declare_plugin
{
  MYSQL_FTPARSER_PLUGIN,      /* type                            */
  &simple_parser_descriptor,  /* descriptor                      */
  parser_info.name,           /* name                            */
  parser_info.author,         /* author                          */
  parser_info.description,    /* description                     */
  PLUGIN_LICENSE_GPL,         /* plugin license                  */
  simple_parser_plugin_init,  /* init function (when loaded)     */
  simple_parser_plugin_deinit,/* deinit function (when unloaded) */
  0x0001,                     /* version                         */
  simple_status               /* status variables                */
}
mysql_declare_plugin_end;
Set up the plugin descriptor.
            Each plugin declaration in the library descriptor points to
            a type-specific descriptor for the corresponding plugin. In
            the simple_parser declaration, that
            descriptor is indicated by
            &simple_parser_descriptor. The
            descriptor specifies the version number for the full-text
            plugin interface (as given by
            MYSQL_FTPARSER_INTERFACE_VERSION), and
            the plugin's parsing, initialization, and deinitialization
            functions:
          
static struct st_mysql_ftparser simple_parser_descriptor=
{
  MYSQL_FTPARSER_INTERFACE_VERSION, /* interface version      */
  simple_parser_parse,              /* parsing function       */
  simple_parser_init,               /* parser init function   */
  simple_parser_deinit              /* parser deinit function */
};
Set up the plugin interface functions.
            The general plugin descriptor in the library descriptor
            names the initialization and deinitialization functions that
            the server should invoke when it loads and unloads the
            plugin. For simple_parser, these
            functions do nothing but return zero to indicate that they
            succeeded:
          
static int simple_parser_plugin_init(void)
{
  return(0);
}
static int simple_parser_plugin_deinit(void)
{
  return(0);
}
Because those functions do not actually do anything, you could omit them and specify 0 for each of them in the plugin declaration.
            The type-specific plugin descriptor for
            simple_parser names the initialization,
            deinitialization, and parsing functions that the server
            invokes when the plugin is used. For
            simple_parser, the initialization and
            deinitialization functions do nothing:
          
static int simple_parser_init(MYSQL_FTPARSER_PARAM *param)
{
  return(0);
}
static int simple_parser_deinit(MYSQL_FTPARSER_PARAM *param)
{
  return(0);
}
Here too, because those functions do nothing, you could omit them and specify 0 for each of them in the plugin descriptor.
            The main parsing function,
            simple_parser_parse(), acts as a
            replacement for the built-in full-text parser, so it needs
            to split text into words and pass each word to the server.
            The parsing function's first argument is a pointer to a
            structure that contains the parsing context. This structure
            has a doc member that points to the text
            to be parsed, and a length member that
            indicates how long the text is. The simple parsing done by
            the plugin considers nonempty runs of whitespace characters
            to be words, so it identifies words like this:
          
static int simple_parser_parse(MYSQL_FTPARSER_PARAM *param)
{
  char *end, *start, *docend= param->doc + param->length;
  for (end= start= param->doc;; end++)
  {
    if (end == docend)
    {
      if (end > start)
        add_word(param, start, end - start);
      break;
    }
    else if (isspace(*end))
    {
      if (end > start)
        add_word(param, start, end - start);
      start= end + 1;
    }
  }
  return(0);
}
            As the parser finds each word, it invokes a function
            add_word() to pass the word to the
            server. add_word() is a helper function
            only; it is not part of the plugin interface. The parser
            passes the parsing context pointer to
            add_word(), as well as a pointer to the
            word and a length value:
          
static void add_word(MYSQL_FTPARSER_PARAM *param, char *word, size_t len)
{
  MYSQL_FTPARSER_BOOLEAN_INFO bool_info=
    { FT_TOKEN_WORD, 0, 0, 0, 0, ' ', 0 };
  param->mysql_add_word(param, word, len, &bool_info);
}
            For boolean-mode parsing, add_word()
            fills in the members of the bool_info
            structure as described in
            Section 22.2.4.2.1, “Full-Text Parser Plugin Data Structures and Functions”.
          
            Set up the status variables, if there are any. For the
            simple_parser plugin, the following
            status variable array sets up one status variable with a
            value that is static text, and another with a value that is
            stored in a long integer variable:
          
long number_of_calls= 0;
struct st_mysql_show_var simple_status[]=
{
  {"static", (char *)"just a static text", SHOW_CHAR},
  {"called", (char *)&number_of_calls,     SHOW_LONG},
  {0,0,0}
};
            When the plugin is installed, the plugin name and the
            name value are joined with an underscore
            to form the name displayed by SHOW
            STATUS. For the array just shown, the resulting
            status variable names are
            simple_parser_static and
            simple_parser_called. This convention
            means that you can easily display the variables for a plugin
            using its name:
          
mysql> SHOW STATUS LIKE 'simple_parser%';
+----------------------+--------------------+
| Variable_name        | Value              |
+----------------------+--------------------+
| simple_parser_static | just a static text |
| simple_parser_called | 0                  |
+----------------------+--------------------+
Compile the plugin library as a shared library and install it in the plugin directory.
              As mentioned earlier, be sure to specify
              -DMYSQL_DYNAMIC_PLUGIN as part of the
              compilation command when you build the plugin.
            
            The procedure for compiling shared objects varies from
            system to system. If you build your library using the GNU
            autotools, libtool should be able to
            generate the correct compilation commands for your system.
            If the library is named mypluglib, you
            should end up with a shared object file that has a name
            something like libmypluglib.so. (The
            file name might have a different extension on your system.)
          
            To use the autotools, you'll need to make a few changes to
            the configuration files at this point to enable the plugin
            to be compiled and installed. Assume that your MySQL
            distribution is installed at a base directory of
            /usr/local/mysql and that its header
            files are located in the include
            directory under the base directory.
          
            Edit Makefile.am, which should look
            something like this:
          
pkgplugindir=$(pkglibdir)/plugin
INCLUDES= -I$(top_builddir)/include -I$(top_srcdir)/include
#noinst_LTLIBRARIES= mypluglib.la
pkgplugin_LTLIBRARIES= mypluglib.la
mypluglib_la_SOURCES= plugin_example.c
mypluglib_la_LDFLAGS= -module -rpath $(pkgplugindir) \
        -L$(libdir)/mysql -lmysqlservices
mypluglib_la_CFLAGS= -DMYSQL_DYNAMIC_PLUGIN
            The mypluglib_la_CFLAGS line takes care
            of passing the -DMYSQL_DYNAMIC_PLUGIN
            flag to the compilation command.
          
            Adjust the INCLUDES line to specify the
            path name to the installed MySQL header files. Edit it to
            look like this:
          
INCLUDES= -I/usr/local/mysql/include
            Make sure that the noinst_LTLIBRARIES
            line is commented out or remove it. Make sure that the
            pkglib_LTLIBRARIES line is not commented
            out; it enables the make install command.
          
            The -lmysqlservices flag is needed to
            link in any functions from services provided through the
            plugin services interface. See
            Section 22.2.6, “MySQL Services for Plugins”.
          
Set up the files needed for the configure command, invoke it, and run make:
shell>autoreconf --force --install --symlinkshell>./configure --prefix=/usr/local/mysqlshell>make
            The --prefix option to
            configure indicates the MySQL base
            directory under which the plugin should be installed. You
            can see what value to use for this option with
            SHOW VARIABLES:
          
mysql> SHOW VARIABLES LIKE 'basedir';
+---------------+------------------+
| Variable_name | Value            |
+---------------+------------------+
| base          | /usr/local/mysql |
+---------------+------------------+
            The location of the plugin directory where you should
            install the library is given by the
            plugin_dir system variable.
            For example:
          
mysql> SHOW VARIABLES LIKE 'plugin_dir';
+---------------+-----------------------------------+
| Variable_name | Value                             |
+---------------+-----------------------------------+
| plugin_dir    | /usr/local/mysql/lib/mysql/plugin |
+---------------+-----------------------------------+
To install the plugin library, use make:
shell> make install
Verify that make install installed the plugin library in the proper directory. After installing it, make sure that the library permissions allow it to be executed by the server.
Register the plugin with the server.
            The INSTALL PLUGIN statement
            causes the server to register the plugin in the
            plugin table and to load the plugin code
            from the library file. Use that statement to register
            simple_parser with the server, and then
            verify that the plugin is listed in the
            plugin table:
          
mysql>INSTALL PLUGIN simple_parser SONAME 'libmypluglib.so';Query OK, 0 rows affected (0.00 sec) mysql>SELECT * FROM mysql.plugin;+---------------+-----------------+ | name | dl | +---------------+-----------------+ | simple_parser | libmypluglib.so | +---------------+-----------------+ 1 row in set (0.00 sec)
For additional information about plugin loading, see Section 12.4.3.1, “Installing and Uninstalling Plugins”.
Try the plugin.
            Create a table that contains a string column and associate
            the parser plugin with a FULLTEXT index
            on the column:
          
mysql>CREATE TABLE t (c VARCHAR(255),->FULLTEXT (c) WITH PARSER simple_parser);Query OK, 0 rows affected (0.01 sec)
Insert some text into the table and try some searches. These should verify that the parser plugin treats all nonwhitespace characters as word characters:
mysql>INSERT INTO t VALUES->('latin1_general_cs is a case-sensitive collation'),->('I\'d like a case of oranges'),->('this is sensitive information'),->('another row'),->('yet another row');Query OK, 5 rows affected (0.02 sec) Records: 5 Duplicates: 0 Warnings: 0 mysql>SELECT c FROM t;+-------------------------------------------------+ | c | +-------------------------------------------------+ | latin1_general_cs is a case-sensitive collation | | I'd like a case of oranges | | this is sensitive information | | another row | | yet another row | +-------------------------------------------------+ 5 rows in set (0.00 sec) mysql>SELECT MATCH(c) AGAINST('case') FROM t;+--------------------------+ | MATCH(c) AGAINST('case') | +--------------------------+ | 0 | | 1.2968142032623 | | 0 | | 0 | | 0 | +--------------------------+ 5 rows in set (0.00 sec) mysql>SELECT MATCH(c) AGAINST('sensitive') FROM t;+-------------------------------+ | MATCH(c) AGAINST('sensitive') | +-------------------------------+ | 0 | | 0 | | 1.3253291845322 | | 0 | | 0 | +-------------------------------+ 5 rows in set (0.01 sec) mysql>SELECT MATCH(c) AGAINST('case-sensitive') FROM t;+------------------------------------+ | MATCH(c) AGAINST('case-sensitive') | +------------------------------------+ | 1.3109166622162 | | 0 | | 0 | | 0 | | 0 | +------------------------------------+ 5 rows in set (0.01 sec) mysql>SELECT MATCH(c) AGAINST('I\'d') FROM t;+--------------------------+ | MATCH(c) AGAINST('I\'d') | +--------------------------+ | 0 | | 1.2968142032623 | | 0 | | 0 | | 0 | +--------------------------+ 5 rows in set (0.01 sec)
Note how neither “case” nor “insensitive” match “case-insensitive” the way that they would for the built-in parser.

User Comments
Add your own comment.