要添加原生 MySQL 函数,请使用此处描述的过程,这需要您使用源代码发行版。您无法将原生函数添加到二进制发行版中,因为需要修改 MySQL 源代码并从修改后的源代码编译 MySQL。如果迁移到其他版本的 MySQL(例如,当新版本发布时),则必须使用新版本重复该过程。
如果将在将被复制到副本的语句中引用原生函数,则必须确保每个副本也具有该函数。否则,当副本尝试调用该函数时,复制将失败。
要添加原生函数,请按照以下步骤修改 sql
目录中的源文件:
-
在
item_create.cc
中为该函数创建一个子类。如果该函数采用固定数量的参数,请分别创建
Create_func_arg0
、Create_func_arg1
、Create_func_arg2
或Create_func_arg3
的子类,具体取决于该函数是否采用零个、一个、两个或三个参数。有关示例,请参阅Create_func_uuid
、Create_func_abs
、Create_func_pow
和Create_func_lpad
类。如果该函数采用可变数量的参数,请创建
Create_native_func
的子类。有关示例,请参阅Create_func_concat
。
-
要提供一个名称,以便可以在 SQL 语句中引用该函数,请通过在以下数组中添加一行来在
item_create.cc
中注册该名称:static Native_func_registry func_array[]
您可以为同一个函数注册多个名称。例如,请参阅
"LCASE"
和"LOWER"
的行,它们是Create_func_lcase
的别名。 在
item_func.h
中,声明一个继承自Item_num_func
或Item_str_func
的类,具体取决于您的函数是返回数字还是字符串。-
在
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()
。 -
如果该函数是非确定性的,请在项构造函数中包含以下语句,以指示不应缓存函数结果:
current_thd->lex->safe_to_cache_query=0;
如果一个函数对于其参数的固定值,可以在不同的调用中返回不同的结果,则该函数是非确定性的。
-
您可能还应该定义以下对象函数:
void Item_func_newname::fix_length_and_dec()
此函数至少应根据给定的参数计算
max_length
。max_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
。所有当前字符串函数都尽量避免分配任何内存,除非绝对必要!