扩展 MySQL 9.0  /  ...  /  服务器插件库和插件描述符

4.4.2.1 服务器插件库和插件描述符

每个包含服务器插件的插件库都必须包含一个库描述符,该描述符包含文件中每个服务器插件的通用插件描述符。本节讨论如何为服务器插件编写库和通用描述符。

库描述符必须定义两个符号

  • _mysql_plugin_interface_version_ 指定通用插件框架的版本号。这由 MYSQL_PLUGIN_INTERFACE_VERSION 符号给出,该符号在 plugin.h 文件中定义。

  • _mysql_plugin_declarations_ 定义一个插件声明数组,以所有成员设置为 0 的声明结束。每个声明都是 st_mysql_plugin 结构的实例(也在 plugin.h 中定义)。库中的每个服务器插件都必须有一个这样的声明。

如果服务器在库中找不到这两个符号,它不会将其接受为合法插件库,并会拒绝它并显示错误。这将阻止库用于插件目的,除非它专门构建为插件库。

定义这两个必需符号的常规方法是使用 plugin.h 文件中的 mysql_declare_plugin()mysql_declare_plugin_end

mysql_declare_plugin(name)
 ... one or more server plugin descriptors here ...
mysql_declare_plugin_end;

每个服务器插件都必须有一个通用描述符,该描述符为服务器插件 API 提供信息。通用描述符对所有插件类型具有相同的结构。 plugin.h 文件中的 st_mysql_plugin 结构定义了此描述符

struct st_mysql_plugin
{
  int type;             /* the plugin type (a MYSQL_XXX_PLUGIN value)   */
  void *info;           /* pointer to type-specific plugin descriptor   */
  const char *name;     /* plugin name                                  */
  const char *author;   /* plugin author (for I_S.PLUGINS)              */
  const char *descr;    /* general descriptive text (for I_S.PLUGINS)   */
  int license;          /* the plugin license (PLUGIN_LICENSE_XXX)      */
  int (*init)(void *);  /* the function to invoke when plugin is loaded */
  int (*deinit)(void *);/* the function to invoke when plugin is unloaded */
  unsigned int version; /* plugin version (for I_S.PLUGINS)             */
  struct st_mysql_show_var *status_vars;
  struct st_mysql_sys_var **system_vars;
  void * __reserved1;   /* reserved for dependency checking             */
  unsigned long flags;  /* flags for plugin */
};

st_mysql_plugin 描述符结构成员的使用方式如下。 char * 成员应指定为以 null 结尾的字符串。

  • type: 插件类型。这必须是 plugin.h 中的插件类型值之一。

    /*
      The allowable types of plugins
    */
    #define MYSQL_UDF_PLUGIN 0                /* User-defined function        */
    #define MYSQL_STORAGE_ENGINE_PLUGIN 1     /* Storage Engine               */
    #define MYSQL_FTPARSER_PLUGIN 2           /* Full-text parser plugin      */
    #define MYSQL_DAEMON_PLUGIN 3             /* The daemon/raw plugin type */
    #define MYSQL_INFORMATION_SCHEMA_PLUGIN 4 /* The I_S plugin type */
    #define MYSQL_AUDIT_PLUGIN 5              /* The Audit plugin type        */
    #define MYSQL_REPLICATION_PLUGIN 6        /* The replication plugin type */
    #define MYSQL_AUTHENTICATION_PLUGIN 7     /* The authentication plugin type */
    #define MYSQL_VALIDATE_PASSWORD_PLUGIN 8  /* validate password plugin type */
    #define MYSQL_GROUP_REPLICATION_PLUGIN 9  /* The Group Replication plugin */
    #define MYSQL_KEYRING_PLUGIN 10           /* The Keyring plugin type   */
    #define MYSQL_CLONE_PLUGIN 11             /* The Clone plugin type   */

    例如,对于全文解析器插件,type 值为 MYSQL_FTPARSER_PLUGIN

  • info: 指向插件类型特定描述符的指针。此描述符的结构取决于特定类型的插件,与通用插件描述符结构不同。为了版本控制目的,每种插件类型类型特定描述符的第一个成员预计将是该类型的接口版本。这使服务器能够检查每种插件的类型特定版本,无论其类型是什么。在版本号之后,描述符包含任何其他必要的成员,例如回调函数和其他服务器正确调用插件所需的信息。后面的章节将描述编写特定类型的服务器插件时,其类型特定描述符的结构。

  • name: 提供插件名称的字符串。这是将在 mysql.plugin 表中列出的名称,以及您在 SQL 语句中引用插件的名称,例如 INSTALL PLUGINUNINSTALL PLUGIN,或使用 --plugin-load 选项。该名称也显示在 INFORMATION_SCHEMA.PLUGINS 表中或 SHOW PLUGINS 的输出中。

    插件名称不应以任何服务器选项的名称开头。如果开头,服务器将无法初始化它。例如,服务器有一个 --socket 选项,因此您不应使用诸如 socketsocket_plugin 等等的插件名称。

  • author: 命名插件作者的字符串。这可以是您想要的任何内容。

  • desc: 提供插件一般描述的字符串。这可以是您想要的任何内容。

  • license: 插件许可证类型。该值可以是 PLUGIN_LICENSE_PROPRIETARYPLUGIN_LICENSE_GPLPLUGIN_LICENSE_BSD 之一。

  • init: 一次性初始化函数,或如果不存在此类函数,则为 NULL。服务器在加载插件时执行此函数,这对于 INSTALL PLUGIN 而言,或者对于在 mysql.plugin 表中列出的插件,在服务器启动时执行。该函数接受一个参数,该参数指向用于标识插件的内部结构。它对成功返回零,对失败返回非零值。

  • deinit: 一次性反初始化函数,或如果不存在此类函数,则为 NULL。服务器在卸载插件时执行此函数,这对于 UNINSTALL PLUGIN 而言,或者对于在 mysql.plugin 表中列出的插件,在服务器关闭时执行。该函数接受一个参数,该参数指向用于标识插件的内部结构。它对成功返回零,对失败返回非零值。

  • version: 插件版本号。安装插件后,可以从 INFORMATION_SCHEMA.PLUGINS 表中检索此值。该值包括主版本号和次版本号。如果您将该值写为十六进制常量,则格式为 0xMMNN,其中 MMNN 分别为主版本号和次版本号。例如,0x0302 代表版本 3.2。

  • status_vars: 指向与插件关联的状态变量结构的指针,或者如果不存在此类变量,则为 NULL。安装插件后,这些变量将显示在 SHOW STATUS 语句的输出中。

    如果 status_vars 成员不为 NULL,则它指向一个 st_mysql_show_var 结构数组,该数组描述状态变量。请参见 第 4.4.2.2 节,“服务器插件状态和系统变量”

  • system_vars: 指向与插件关联的系统变量结构的指针,或者如果不存在此类变量,则为 NULL。这些选项和系统变量可用于帮助初始化插件内的变量。安装插件后,这些变量将显示在 SHOW VARIABLES 语句的输出中。

    如果 system_vars 成员不为 NULL,则它指向一个 st_mysql_sys_var 结构数组,该数组描述系统变量。请参见 第 4.4.2.2 节,“服务器插件状态和系统变量”

  • __reserved1: 未来的占位符。它应该设置为 NULL

  • flags: 插件标志。各个位对应于不同的标志。该值应设置为适用标志的 OR。这些标志可用

    #define PLUGIN_OPT_NO_INSTALL   1UL   /* Not dynamically loadable */
    #define PLUGIN_OPT_NO_UNINSTALL 2UL   /* Not dynamically unloadable */
    #define PLUGIN_OPT_ALLOW_EARLY  4UL   /* allow --early-plugin-load */

    启用时,这些标志具有以下含义

服务器仅在加载和卸载插件时才会调用通用插件描述符中的 initdeinit 函数。它们与插件的使用无关,例如当 SQL 语句导致插件被调用时。

例如,包含名为 simple_parser 的单个全文解析器插件的库的描述符信息如下所示

mysql_declare_plugin(ftexample)
{
  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                */
  simple_system_variables,    /* system variables                */
  NULL,
  0
}
mysql_declare_plugin_end;

对于全文解析器插件,类型必须为 MYSQL_FTPARSER_PLUGIN。这是将插件识别为在创建 FULLTEXT 索引时在 WITH PARSER 子句中合法使用的值。(没有其他插件类型对该子句合法。)

plugin.h 定义了 mysql_declare_plugin()mysql_declare_plugin_end 宏,如下所示

#ifndef MYSQL_DYNAMIC_PLUGIN
#define __MYSQL_DECLARE_PLUGIN(NAME, VERSION, PSIZE, DECLS) \
MYSQL_PLUGIN_EXPORT int VERSION= MYSQL_PLUGIN_INTERFACE_VERSION; \
MYSQL_PLUGIN_EXPORT int PSIZE= sizeof(struct st_mysql_plugin); \
MYSQL_PLUGIN_EXPORT struct st_mysql_plugin DECLS[]= {
#else
#define __MYSQL_DECLARE_PLUGIN(NAME, VERSION, PSIZE, DECLS) \
MYSQL_PLUGIN_EXPORT int _mysql_plugin_interface_version_= MYSQL_PLUGIN_INTERFACE_VERSION; \
MYSQL_PLUGIN_EXPORT int _mysql_sizeof_struct_st_plugin_= sizeof(struct st_mysql_plugin); \
MYSQL_PLUGIN_EXPORT 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,0,0,0,0}}
注意

这些声明仅在定义了 MYSQL_DYNAMIC_PLUGIN 符号时才定义 _mysql_plugin_interface_version_ 符号。这意味着必须提供 -DMYSQL_DYNAMIC_PLUGIN 作为编译命令的一部分,以将插件构建为共享库。

当宏像上面那样使用时,它们会扩展到以下代码,该代码定义了两个必需的符号(_mysql_plugin_interface_version__mysql_plugin_declarations_

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_[]= {
{
  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                */
  simple_system_variables,    /* system variables                */
  NULL,
  0
}
  ,{0,0,0,0,0,0,0,0,0,0,0,0}}
};

前面的示例在一般描述符中声明了一个插件,但可以声明多个插件。将声明一个接一个地列在 mysql_declare_plugin()mysql_declare_plugin_end 之间,用逗号分隔。

MySQL 服务器插件必须编译为 C++ 代码。您不应该使用的 C++ 功能之一是非常量变量来初始化全局结构。应仅使用常量变量初始化结构的成员,例如 st_mysql_plugin 结构。前面显示的 simple_parser 描述符在 C++ 插件中是允许的,因为它满足该要求

mysql_declare_plugin(ftexample)
{
  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                */
  simple_system_variables,    /* system variables                */
  NULL,
  0
}
mysql_declare_plugin_end;

以下是编写一般描述符的另一种有效方法。它使用常量变量来指示插件名称、作者和描述

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(ftexample)
{
  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                */
  simple_system_variables,    /* system variables                */
  NULL,
  0
}
mysql_declare_plugin_end;

但是,以下一般描述符无效。它使用结构成员来指示插件名称、作者和描述,但在 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(ftexample)
{
  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                */
  simple_system_variables,    /* system variables                */
  NULL,
  0
}
mysql_declare_plugin_end;