擴充 MySQL 8.4  /  ...  /  伺服器外掛程式庫和外掛程式描述符

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;