ITEEDU

27.2.3. 添加新的自定义函数

27.2.3.1. UDF对简单函数的调用顺序
27.2.3.2. UDF对集合函数的调用顺序
27.2.3.3. UDF参量处理
27.2.3.4. UDF返回值和错误处理
27.2.3.5. 编译和安装自定义函数
27.2.3.6. 自定义函数安全预报措施

要使得UDF机制能够起作用,必须使用C或者C++编写函数,你的系统必须支持动态加载。MySQL 源码分发版包括一个sql/udf_example.cc 文件,此文件定义了5个新函数。可以参考这个文件,看UDF是如何调用常规工作。

为了能使用UDF,你需要动态链接mysqld。不要配置MySQL使用--with-mysqld-ldflags=-all-static参数。如果你想使用一个需要从mysqld 访问符号的UDF(例如在使用default_charset_info的sql/udf_example.cc文件中的metaphone函数),你必须使用-rdynamic参数来链接程序(参阅man dlopen)。如果你计划使用UDF, 一个经验法则就是,用with-mysqld-ldflags=-rdynamic设定MySQL,除非你有很好的理由不去这么做。

如果你使用的是预编译分发版的MySQL, 请使用MySQL-Max,其中含有一个动态链接了的服务器,它可以支持动态加载。

对于每个你想要使用在SQL声明中的函数,你应该定义相应的C (或 C++)函数。在下面的讨论中,xxx用来表示范例函数的名字,为了区分使用SQL还是C/C++,xxx()(上标)表示SQL函数调用,xxx()(下标)表示C/C++函数调用。

你为xxx()编写来实现接口的C/C++ 函数如下:

  • xxx() (必有)

    主函数。 这是函数结果被计算的地方。SQL函数数据类型与C/C++函数返回类型的对应关系如下:

    SQL 类型 C/C++ 类型
    STRING char *
    INTEGER long long
    REAL double
  • xxx_init() (可选)

    对xxx()的初始化函数。它可以被用来:

    • 检查传递给xxx()的参量数目。

    • 检查参量是否为必需的类型,或者,除此之外,在主函数被调用的时候告诉MySQL将参量强制为想要的类型。

    • 分配主函数需要的内存。

    • 指定结果的最大长度。

    • 指定(对于REAL 函数)小数的最多位数。

    • 指定结果是否可以为 NULL。

  • xxx_deinit() (可选)

    对xxx()的去初始化函数。它释放初始化函数分配的内存。

当SQL声明调用XXX()时,MySQL调用初始化函数xxx_init(),让它执行必要的设置,比如,检查 参量或分配内存。如果xxx_init() 返回一个错误,SQL声明会退出并给出错误信息,而主函数和去初始化函数并没有被调用。 否则,主函数xxx() 对每一行都被调用一次。所有行都处理完之后,调用去初始化函数xxx_deinit() 执行必要的清除。

对于象SUM()一样工作的集合函数,你也必须提供如下的函数:

  • xxx_clear() (在5.1节中必须)

    对一个新组重置当前集合值为初试集合值,但不插入任何参量。

  • xxx_add() (必须)

    添加参量到当前集合值。

MySQL 按下列操作来处理集合UDF:

  1. 调用 xxx_init() 让集合函数分配它需要用来存储结果的内存。

  2. 按照GROUP BY表达式来排序表。

  3. 为每个新组中的第一行调用xxx_clear()函数。

  4. 为属于同组的每一个新行调用xxx_add()函数。

  5. 当组改变时或每组的最后一行被处理完之后,调用xxx()来获取集合结果。

  6. 重复,以上3-步直到所有行被处理完。

  7. 调用xxx_deinit() 函数去释放UDF分配的内存。.

所有函数必须时线程安全的,这不仅对主函数,对初始化和去初始化函数也一样,也包括集合函数要求的附加函数。这个要求的一个结果就是,你不能分配任何变化的全局或静态变量。如果你需要内存,你可以在xxx_init()函数分配内存,然后在xxx_deinit()函数释放掉。