10.2 将扩展对象添加到MySQL Shell

  • 10.2.1 创建用户定义的MySQL Shell全局对象
  • 10.2.2 创建扩展对象
  • 10.2.3 持久化扩展对象
  • 10.2.4 MySQL Shell 扩展对象示例

从 MySQL Shell 8.0.17 开始,您可以定义扩展对象并将它们作为用户定义的 MySQL Shell 全局对象的一部分提供。当您创建并注册扩展对象时,它在 JavaScript 和 Python 模式下都可用。

扩展对象包括一个或多个成员。成员可以是基本数据类型值、用本机 JavaScript 或 Python 编写的函数或其他扩展对象。您可以使用内置全局对象提供的函数构造和注册扩展对象shell。在使用 MySQL Shell 注册该对象后,您可以通过向其添加更多成员来继续扩展该对象。

笔记

您可以将包含函数的扩展对象直接注册为 MySQL Shell 全局对象。但是,为了更好地管理扩展对象,创建一个或少量顶级扩展对象作为所有扩展对象的入口点,并将这些顶级扩展对象注册为 MySQL Shell 会很有帮助。全局对象。然后,您可以将当前和未来的扩展对象添加为适当的顶级扩展对象的成员。通过这种结构,注册为 MySQL Shell 全局对象的顶级扩展对象为开发人员提供了一个位置,可以添加在不同时间创建并存储在不同 MySQL Shell 插件中的各种扩展对象。

10.2.1 创建用户定义的MySQL Shell全局对象

shell.createExtensionObject()要创建新的 MySQL Shell 全局对象来充当扩展对象的入口点,请首先使用JavaScript 或shell.create_extension_object() Python 中的内置函数创建一个新的顶级扩展对象 :

shell.createExtensionObject()

shell.registerGlobal()然后通过调用JavaScript 或 Python 中的方法 将此顶级扩展对象注册为 MySQL Shell 全局对象 shell.register_global()。该方法的语法如下:

shell.registerGlobal(name, object[, definition])

在哪里:

  • name是一个给出全局对象名称(和类)的字符串。该名称必须是有效的脚本标识符,因此第一个字符必须是字母或下划线字符,后跟任意数量的字母、数字或下划线字符。该名称在您的 MySQL Shell 安装中必须是唯一的,因此它不能是内置 MySQL Shell 全局对象的名称(例如, db, dba, cluster, session, shell, util),并且它不能是您已经用于用户定义的 MySQL Shell 全局对象。下面的示例展示了如何在注册全局对象之前检查名称是否已存在。

    重要的

    当您以 JavaScript 和 Python 模式访问对象时,将按原样使用用于注册全局对象的名称。因此,最好为全局对象使用简单的单字名称(例如 ext)。如果您使用驼峰命名法或蛇形命名法(例如myCustomObject)注册全局对象,则在使用全局对象时,必须指定注册时的名称。仅以适合语言的方式处理成员使用的名称。

  • object是您注册为 MySQL Shell 全局对象的扩展对象。您只能注册一次扩展对象。

  • definition是一个可选字典,其中包含 MySQL Shell 帮助系统中提供的全局对象的帮助信息。该字典包含以下键:

    • brief(字符串,可选):作为帮助信息提供的全局对象的简短描述。

    • details(字符串列表,可选):作为帮助信息提供的全局对象的详细描述。

      10.2.2 创建扩展对象

      shell.createExtensionObject()要创建新的扩展对象以提供一个或多个函数、数据类型或更进一步的扩展对象,请使用JavaScript 或Python 中 的内置函数 shell.create_extension_object()

      shell.createExtensionObject()

      shell.addExtensionObjectMember()要将成员添加到扩展对象,请使用JavaScript 或 Python 中的 内置 函数shell.add_extension_object_member()

      shell.addExtensionObjectMember(object, name, member[, definition])

      在哪里:

      • object是要添加新成员的扩展对象。

      • name是新成员的名字。该名称必须是有效的脚本标识符,因此第一个字符必须是字母或下划线字符,后跟任意数量的字母、数字或下划线字符。该名称在已添加到同一扩展对象的成员中必须是唯一的,如果该成员是函数,则该名称不必与定义的函数的名称匹配。即使您使用 Python 定义和添加成员,名称也最好以驼峰式大小写指定。以驼峰式大小写指定成员名称使 MySQL Shell 能够自动强制执行命名约定。 MySQL Shell 使该成员可以在 JavaScript 模式下使用驼峰式大小写,在 Python 模式下使用蛇形大小写。

      • member是新成员的值,可以是以下任意值:

        • 支持的基本数据类型。支持的数据类型为 “ none ”或“ null ”、 “ bool ”、“ number ”(整数或浮点)、“ string ”、 “ array ”和“ dictionary ”。
        • JavaScript 或 Python 函数。您可以在作为成员添加到扩展对象的函数主体中使用本机代码,前提是接口(参数和返回值)仅限于表 10.1“扩展对象支持的数据类型对”中支持的数据类型。在接口中使用其他数据类型可能会导致未定义的行为。
        • 另一个扩展对象。
      • definition是一个可选字典,可以包含成员的帮助信息,如果成员是函数,则还可以包含该函数接收的参数列表。帮助信息使用以下属性定义:

        • brief是对该成员的简要描述。
        • details是成员的详细描述,以字符串列表的形式提供。这是当您使用 MySQL Shell \help命令时提供的。

        函数的参数使用以下属性定义:

        • parameters是描述函数接收的每个参数的字典列表。每个字典描述一个参数,并且可以包含以下键:
          • name(字符串,必需):参数的名称。
          • type(字符串,必需):参数的数据类型,“字符串”、 “整数”、“布尔”、 “浮点数”、“数组”、 “字典”或“对象”之一。如果类型是“ object ”, 也可以使用class或键。classes如果类型是 “ string ”,values 也可以使用key。如果类型是 “字典”, options也可以使用key。
          • class(字符串,可选,数据类型为“ object ”时允许):定义允许作为参数的对象类型。
          • classes(字符串列表,可选,当数据类型为“ object ”时允许):定义允许作为参数的对象类型的类列表。class和 受支持的对象类型 classes是由 MySQL Shell API 公开的对象类型,例如 SessionClassicSessionTableCollection。如果将对象类型传递给不在此列表中的函数,则会引发错误。
          • values(字符串列表,可选,当数据类型为“ string ”时允许):对参数有效的值列表。如果将值传递给不在此列表中的函数,则会引发错误。
          • options(选项列表,可选,数据类型为“字典”时允许):参数允许的选项列表。选项使用与参数相同的定义结构,但如果 required没有为选项指定,则默认为false. MySQL Shell 验证最终用户指定的选项,如果将选项传递给不在此列表中的函数,则会引发错误。在 MySQL Shell 8.0.17 到 8.0.19 中,当数据类型为“ dictionary ”时,该参数是必需的,但从 MySQL Shell 8.0.20 开始,该参数是可选的。如果您创建一个没有选项列表的字典,则最终用户为字典指定的任何选项都会由 MySQL Shell 直接传递给该函数,而无需进行验证。
          • required(bool, 可选):该参数是否为必填。如果 required未指定参数,则默认为true
          • brief(字符串,可选):作为帮助信息提供的参数的简短描述。
          • details(字符串列表,可选):作为帮助信息提供的参数的详细描述。

      扩展对象被视为正在构建,直到它被注册为 MySQL Shell 全局对象,或者作为成员添加到注册为 MySQL Shell 全局对象的另一个扩展对象。如果您尝试在 MySQL Shell 中使用尚未注册的扩展对象,则会返回错误。

      跨语言注意事项

      扩展对象可以包含 Python 中定义的成员和 JavaScript 中定义的成员的混合。 MySQL Shell 管理从一种语言到另一种语言的数据传输作为参数和返回值。 表 10.1“扩展对象支持的数据类型对”显示了在语言之间传输数据时 MySQL Shell 支持的数据类型,以及用作彼此表示的数据类型对:

      表 10.1 扩展对象支持的数据类型对

      JavaScript Python
      布尔值 布尔值
      细绳 细绳
      整数 长的
      数字 漂浮
      无效的 没有任何
      大批 列表
      地图 字典

      扩展对象在两种语言中实际上是相同的对象。

10.2.3 持久化扩展对象

用于定义和注册扩展对象的脚本必须具有.jsJavaScript 代码或 .pyPython 代码的文件扩展名,以匹配脚本所使用的语言。文件扩展名不区分大小写。

持久保存扩展对象的首选方法是将其添加到 MySQL Shell 插件中。 MySQL Shell 启动时会自动加载插件和插件组,并且它们定义和注册的函数立即可用。在 MySQL Shell 插件中,包含初始化脚本的文件必须命名init.jsinit.py适合语言。插件只能包含一种语言的代码,因此,如果您要创建一个混合了 Python 中定义的成员和 JavaScript 中定义的成员的扩展对象,则必须将这些成员存储为单独的适合语言的插件。有关使用 MySQL Shell 插件的说明,请参阅 第 10.3 节 “MySQL Shell 插件”。

作为替代方案,包含扩展对象的脚本可以直接存储在init.dMySQL Shell 用户配置路径的文件夹中。当 MySQL Shell 启动时,在init.d文件夹中找到的带有 .js.py文件扩展名的所有文件都会自动处理,并且它们注册的函数将可用。 (在此位置,文件名对于 MySQL Shell 来说并不重要。)默认的 MySQL Shell 用户配置路径位于~/.mysqlsh/Unix 和 %AppData%\MySQL\mysqlsh\Windows 上。通过定义环境变量,可以在所有平台上覆盖用户配置路径 MYSQLSH_USER_CONFIG_HOME

10.2.4 MySQL Shell 扩展对象示例

示例 10.1 创建和注册扩展对象 - Python

hello_world() 此示例创建一个可通过用户定义的 MySQL Shell 全局对象使用的 函数demo。该代码创建一个新的扩展对象并将该hello_world() 函数作为成员添加到其中,然后将该扩展对象注册为 MySQL Shell 全局对象demo

解释# Define a hello_world function that will be exposed by the global object 'demo'
def hello_world():
print("Hello world!")

# Create an extension object where the hello_world function will be registered
plugin_obj = shell.create_extension_object()

shell.add_extension_object_member(plugin_obj, "helloWorld", hello_world,
{"brief": "Prints 'Hello world!'", "parameters": []})

# Registering the 'demo' global object
shell.register_global("demo", plugin_obj,
{"brief": "A demo plugin that showcases MySQL Shell's plugin feature."})

请注意,函数中的成员名称以驼峰式大小写指定 shell.add_extension_object_member()。当您以 Python 模式调用成员时,成员名称使用蛇形大小写,MySQL Shell 会自动处理转换。在 JavaScript 模式下,该函数的调用方式如下:

mysql-js> demo.helloWorld()

在Python模式下,该函数的调用方式如下:

mysql-py> demo.hello_world()

示例 10.2 创建和注册扩展对象 - JavaScript

此示例创建一个以函数 listTables()作为成员的扩展对象,并将其直接注册为 MySQL Shell 全局对象 tools

解释// Define a listTables function that will be exposed by the global object tools

function listTables(session, schemaName, options) {
...
}

// Create an extension object and add the listTables function to it as a member

var object = shell.createExtensionObject()

shell.addExtensionObjectMember(object, "listTables", listTables,

{
brief:"Retrieves the tables from a given schema.",
details: ["Retrieves the tables of the schema named schemaName.",
"If excludeCollections is true, the collection tables will not be returned"],
parameters:
[
{
name: "session",
type: "object",
class: "Session",
brief: "An X Protocol session object."
},
{
name: "schemaName",
type: "string",
brief: "The name of the schema from which the table list will be pulled."
},
{
name: "options",
type: "dictionary",
brief: "Additional options that affect the function behavior.",
options: [
{
name: "excludeViews",
type: "bool",
brief: "If set to true, the views will not be included on the list, default is false",
},
{
name: "excludeCollections",
type: "bool",
brief: "If set to true, the collections will not be included on the list, default is false",
}
]
},
]
});

// Register the extension object as the global object "tools"

shell.registerGlobal("tools", object, {brief:"Global object for ExampleCom administrator tools",
details:[
"Global object to access homegrown ExampleCom administrator tools.",
"Add new tools to this global object as members with shell.addExtensionObjectMember()."]})

在 JavaScript 模式下,该函数的调用方式如下:

mysql-js> tools.listTables(session, "world_x", {excludeViews: true})

在Python模式下,该函数的调用方式如下:

mysql-py> tools.list_tables(session, "world_x", {"excludeViews": True})