扩展 MySQL 9.0  /  向 MySQL 添加函数  /  添加原生函数

6.1 添加原生函数

要添加原生 MySQL 函数,请使用此处描述的过程,这需要您使用源代码发行版。您无法将原生函数添加到二进制发行版中,因为需要修改 MySQL 源代码并从修改后的源代码编译 MySQL。如果迁移到其他版本的 MySQL(例如,当新版本发布时),则必须使用新版本重复该过程。

如果将在将被复制到副本的语句中引用原生函数,则必须确保每个副本也具有该函数。否则,当副本尝试调用该函数时,复制将失败。

要添加原生函数,请按照以下步骤修改 sql 目录中的源文件:

  1. item_create.cc 中为该函数创建一个子类。

    • 如果该函数采用固定数量的参数,请分别创建 Create_func_arg0Create_func_arg1Create_func_arg2Create_func_arg3 的子类,具体取决于该函数是否采用零个、一个、两个或三个参数。有关示例,请参阅 Create_func_uuidCreate_func_absCreate_func_powCreate_func_lpad 类。

    • 如果该函数采用可变数量的参数,请创建 Create_native_func 的子类。有关示例,请参阅 Create_func_concat

  2. 要提供一个名称,以便可以在 SQL 语句中引用该函数,请通过在以下数组中添加一行来在 item_create.cc 中注册该名称:

    static Native_func_registry func_array[]

    您可以为同一个函数注册多个名称。例如,请参阅 "LCASE""LOWER" 的行,它们是 Create_func_lcase 的别名。

  3. item_func.h 中,声明一个继承自 Item_num_funcItem_str_func 的类,具体取决于您的函数是返回数字还是字符串。

  4. item_func.cc 中,添加以下声明之一,具体取决于您是要定义数字函数还是字符串函数:

    double   Item_func_newname::val()
    longlong Item_func_newname::val_int()
    String  *Item_func_newname::Str(String *str)

    如果您从任何标准项(如 Item_num_func)继承对象,则您可能只需要定义这些函数之一,并让父对象处理其他函数。例如,Item_str_func 类定义了一个 val() 函数,该函数对 ::str() 返回的值执行 atof()

  5. 如果该函数是非确定性的,请在项构造函数中包含以下语句,以指示不应缓存函数结果:

    current_thd->lex->safe_to_cache_query=0;

    如果一个函数对于其参数的固定值,可以在不同的调用中返回不同的结果,则该函数是非确定性的。

  6. 您可能还应该定义以下对象函数:

    void Item_func_newname::fix_length_and_dec()

    此函数至少应根据给定的参数计算 max_lengthmax_length 是该函数可能返回的最大字符数。如果主函数不能返回 NULL 值,则此函数还应设置 maybe_null = 0。该函数可以通过检查参数的 maybe_null 变量来检查是否有任何函数参数可以返回 NULL。请查看 Item_func_mod::fix_length_and_dec,以获取有关如何执行此操作的典型示例。

所有函数都必须是线程安全的。换句话说,不要在函数中使用任何全局变量或静态变量,而不对其使用互斥锁进行保护。

如果要从 ::val()::val_int()::str() 返回 NULL,则应将 null_value 设置为 1 并返回 0。

对于 ::str() 对象函数,以下附加注意事项适用:

  • String *str 参数提供了一个字符串缓冲区,可用于保存结果。(有关 String 类型的更多信息,请查看 sql_string.h 文件。)

  • ::str() 函数应返回保存结果的字符串,如果结果为 NULL,则返回 (char*) 0

  • 所有当前字符串函数都尽量避免分配任何内存,除非绝对必要!