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 公开的对象类型,例如Session
、ClassicSession
、Table
或Collection
。如果将对象类型传递给不在此列表中的函数,则会引发错误。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 持久化扩展对象
用于定义和注册扩展对象的脚本必须具有.js
JavaScript 代码或 .py
Python 代码的文件扩展名,以匹配脚本所使用的语言。文件扩展名不区分大小写。
持久保存扩展对象的首选方法是将其添加到 MySQL Shell 插件中。 MySQL Shell 启动时会自动加载插件和插件组,并且它们定义和注册的函数立即可用。在 MySQL Shell 插件中,包含初始化脚本的文件必须命名init.js
或 init.py
适合语言。插件只能包含一种语言的代码,因此,如果您要创建一个混合了 Python 中定义的成员和 JavaScript 中定义的成员的扩展对象,则必须将这些成员存储为单独的适合语言的插件。有关使用 MySQL Shell 插件的说明,请参阅 第 10.3 节 “MySQL Shell 插件”。
作为替代方案,包含扩展对象的脚本可以直接存储在init.d
MySQL 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})