35.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))以绕开这个限制, 但最好还是通过使用无冲突的名字来避免这个问题。

另一个可能的冲突是可变的和非可变参数之间的函数关系。 例如,它可以创建foo(numeric)foo(VARIADIC numeric[])。在这种情况下,目前还不清楚哪一个 应匹配提供一个数字参数的调用,如 foo(10.1)。规则是函数早期出现在使用的搜索路径中, 或者如果两个函数都在同样的模式下,非-可变参数优先。

在重载C语言函数的时候,还有一个额外的限制: 重载族的每个函数的C名字必须和所有其它函数的C名字不同, 其它函数包括内部的和动态加载的。如果违反这条规则, 那么行为是不可移植的。你可能会得到一个运行时的链接错误, 或者是其中一个函数被调用(通常是内部的那个)。 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函数名代表许多可能的惯例之一。