This section provides a step-by-step procedure for 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 non-empty runs of whitespace
          characters.
        
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 plugin general declaration 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 plugin general declaration 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 library descriptor and by the plugin descriptors.
          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.1 under your
          current directory:
        
shell>mkdir fulltext_pluginshell>cp mysql-5.1/plugin/fulltext/* fulltext_plugin
          If you are copying files from a BitKeeper 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                            */
  "MySQL AB",                 /* 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}}
              One point to note about those definitions is that the
              _mysql_plugin_interface_version_ symbol
              is defined 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 when you build the plugin.
            
              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                            */
  "MySQL AB",                 /* 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). One feature
              of C++ is that you can use non-constant variables to
              initialize global structures. However, if you write a C++
              plugin, you should not use this feature. Members of
              structures such as the st_mysql_plugin
              structure should be initialized with constant variables.
              See the discussion at the end of this section that
              describes some legal and illegal initializers for plugins.
            
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 declaration 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 non-empty 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
              項25.2.5.2. 「Type-Specific Plugin 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.
              Note: 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
              filename 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:
            
#Makefile.am example for a plugin pkglibdir=$(libdir)/mysql INCLUDES= -I$(top_builddir)/include -I$(top_srcdir)/include #noinst_LTLIBRARIES= mypluglib.la pkglib_LTLIBRARIES= mypluglib.la mypluglib_la_SOURCES= plugin_example.c mypluglib_la_LDFLAGS= -module -rpath $(pkglibdir) 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
              pathname 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.
            
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 |
+---------------+----------------------------+
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 list 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)
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 non-whitespace 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.
          MySQL plugins can be written in C or C++ (or another language
          that can use C calling conventions). One feature of C++ is
          that you can use non-constant variables to initialize global
          structures. However, if you write a C++ plugin, you should not
          use this feature. Members of structures such as the
          st_mysql_plugin structure should be
          initialized 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                            */
  "MySQL AB",                 /* 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 = "MySQL AB";
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",
  "MySQL AB",
  "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;

