扩展 MySQL 9.0  /  ...  /  编写 INFORMATION_SCHEMA 插件

4.4.6 编写 INFORMATION_SCHEMA 插件

本节介绍如何编写服务器端 INFORMATION_SCHEMA 表插件。有关实现此类插件的示例代码,请参阅 MySQL 源代码分发的 sql/sql_show.cc 文件。您还可以查看 InnoDB 源代码中的示例插件。请参阅 InnoDB 源代码树(在 storage/innobase 目录中)中的 handler/i_s.cchandler/ha_innodb.cc 文件。

要编写 INFORMATION_SCHEMA 表插件,请在插件源文件中包含以下头文件。根据插件的功能和要求,可能还需要其他 MySQL 或通用头文件。

#include <sql_class.h>
#include <table.h>

这些头文件位于 MySQL 源代码分发的 sql 目录中。它们包含 C++ 结构,因此 INFORMATION_SCHEMA 插件的源文件必须作为 C++ 代码进行编译。

此处开发的示例插件的源文件名为 simple_i_s_table.cc。它创建一个名为 SIMPLE_I_S_TABLE 的简单 INFORMATION_SCHEMA 表,该表有两个名为 NAMEVALUE 的列。实现该表的插件库的通用描述符如下所示

mysql_declare_plugin(simple_i_s_library)
{
  MYSQL_INFORMATION_SCHEMA_PLUGIN,
  &simple_table_info,                /* type-specific descriptor */
  "SIMPLE_I_S_TABLE",                /* table name */
  "Author Name",                     /* author */
  "Simple INFORMATION_SCHEMA table", /* description */
  PLUGIN_LICENSE_GPL,                /* license type */
  simple_table_init,                 /* init function */
  NULL,
  0x0100,                            /* version = 1.0 */
  NULL,                              /* no status variables */
  NULL,                              /* no system variables */
  NULL,                              /* no reserved information */
  0                                  /* no flags */
}
mysql_declare_plugin_end;

name 成员 (SIMPLE_I_S_TABLE) 指示在语句(如 INSTALL PLUGINUNINSTALL PLUGIN)中引用插件时要使用的名称。这也是 SHOW PLUGINSINFORMATION_SCHEMA.PLUGINS 显示的名称。

通用描述符的 simple_table_info 成员指向类型特定的描述符,该描述符仅包含类型特定的 API 版本号

static struct st_mysql_information_schema simple_table_info =
{ MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION };

通用描述符指向初始化和反初始化函数

  • 初始化函数提供有关表结构的信息以及填充表的函数。

  • 反初始化函数执行任何必要的清理。如果不需要清理,此描述符成员可以为 NULL(如所示示例)。

初始化函数应在成功时返回 0,如果发生错误,则返回 1。该函数接收一个通用指针,它应将其解释为指向表结构的指针

static int table_init(void *ptr)
{
  ST_SCHEMA_TABLE *schema_table= (ST_SCHEMA_TABLE*)ptr;

  schema_table->fields_info= simple_table_fields;
  schema_table->fill_table= simple_fill_table;
  return 0;
}

该函数应设置表结构的这两个成员

  • fields_info:一个包含有关每列信息的 ST_FIELD_INFO 结构的数组。

  • fill_table:填充表的函数。

fields_info 指向的数组应包含 INFORMATION_SCHEMA 每列的一个元素,以及一个终止元素。示例插件的以下 simple_table_fields 数组表明 SIMPLE_I_S_TABLE 有两列。NAME 是字符串类型,长度为 10,VALUE 是整数类型,显示宽度为 20。最后一个结构标记数组的结束。

static ST_FIELD_INFO simple_table_fields[]=
{
  {"NAME", 10, MYSQL_TYPE_STRING, 0, 0 0, 0},
  {"VALUE", 6, MYSQL_TYPE_LONG, 0, MY_I_S_UNSIGNED, 0, 0},
  {0, 0, MYSQL_TYPE_NULL, 0, 0, 0, 0}
};

有关列信息结构的更多信息,请参阅 table.h 头文件中的 ST_FIELD_INFO 定义。允许的 MYSQL_TYPE_xxx 类型值是 C API 中使用的那些值;请参阅 C API 基本数据结构.

fill_table 成员应设置为填充表的函数,并在成功时返回 0,如果发生错误,则返回 1。对于示例插件,simple_fill_table() 函数如下所示

static int simple_fill_table(THD *thd, TABLE_LIST *tables, Item *cond)
{
  TABLE *table= tables->table;

  table->field[0]->store("Name 1", 6, system_charset_info);
  table->field[1]->store(1);
  if (schema_table_store_record(thd, table))
    return 1;
  table->field[0]->store("Name 2", 6, system_charset_info);
  table->field[1]->store(2);
  if (schema_table_store_record(thd, table))
    return 1;
  return 0;
}

对于 INFORMATION_SCHEMA 表的每一行,此函数初始化每一列,然后调用 schema_table_store_record() 来安装该行。store() 方法参数取决于要存储的值类型。对于列 0 (NAME,字符串),store() 接受指向字符串的指针、其长度以及有关字符串字符集的信息

store(const char *to, uint length, CHARSET_INFO *cs);

对于列 1 (VALUE,整数),store() 接受该值以及一个标志,指示它是否无符号

store(longlong nr, bool unsigned_value);

有关如何填充 INFORMATION_SCHEMA 表的其他示例,请在 sql_show.cc 中搜索 schema_table_store_record() 的实例。

要编译和安装插件库文件,请使用 第 4.4.3 节“编译和安装插件库” 中的说明。要使库文件可供使用,请将其安装在插件目录中(由 plugin_dir 系统变量指定的目录)。

要测试插件,请安装它

mysql> INSTALL PLUGIN SIMPLE_I_S_TABLE SONAME 'simple_i_s_table.so';

验证该表是否存在

mysql> SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
    -> WHERE TABLE_NAME = 'SIMPLE_I_S_TABLE';
+------------------+
| TABLE_NAME       |
+------------------+
| SIMPLE_I_S_TABLE |
+------------------+

尝试从中选择

mysql> SELECT * FROM INFORMATION_SCHEMA.SIMPLE_I_S_TABLE;
+--------+-------+
| NAME   | VALUE |
+--------+-------+
| Name 1 |     1 |
| Name 2 |     2 |
+--------+-------+

卸载它

mysql> UNINSTALL PLUGIN SIMPLE_I_S_TABLE;