28.4.3 添加本机功能
要添加本机 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
。 -
除非绝对必要,否则所有当前的字符串函数都将尝试避免分配任何内存!