擴充 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;