32.5. 函数重载

多个函数可以定义成同样的 SQL 名字,只要它们接受的参数不同。 换句话说,函数名可以重载。 在执行一个查询的时候,服务器会从提供的参数的类型和个数上判断应该调用哪个函数。 重载也可以用于模拟有变化个数参数,但是参数有上限的函数。

在创建一族重载函数的时候,我们应该小心避免歧义。比如,给出下面函数

CREATE FUNCTION test(int, real) RETURNS ...
CREATE FUNCTION test(smallint, double precision) RETURNS ...

如果给出一些简单的输入,比如 test(1, 1.5), 系统要想判断出来应该调用哪个函数可不是一件很容易的事情。 目前实现的解析规则在 Chapter 10 里描述, 但是设计一个隐含地以来这些行为的系统可不算明智。

一个接受单个复合类型参数的函数通常不应该和该类型和该类型的任何属性(字段)同名。 记住:attribute(table) 被认为是等效于 table.attribute 的。 在这种情况下,一个复合类型上的函数会和一个复合类型的属性有歧义, 这时候总是会使用属性。我们可以通过使用模式修饰函数名的方法来绕开这限制 (也就是说,schema.func(table)),但是最好通过使用无冲突的名字来避免这个问题。

在重载 C 语言函数的时候,还有一个额外的约束:重载族的每个函数的 C 名字必须和所有其他函数的 C 名字不同,其它函数包括内部的和动态装载的。 如果违反这条规则,那么行为是不可移植的。你可能会得到一个运行时的链接错误, 或者是其中一个函数被调用(通常是内部的那个)。 SQL 命令 CREATE FUNCTION 可选的 AS 子句把 SQL 函数名和 C 源代码里面的函数名分离开。比如,

CREATE FUNCTION test(int) RETURNS int
    AS 'filename', 'test_1arg'
    LANGUAGE C;
CREATE FUNCTION test(int, int) RETURNS int
    AS 'filename', 'test_2arg'
    LANGUAGE C;

这里的 C 函数名代表许多可能的传统之一。