38.6. 函数重载

可以用同样的 SQL 名称定义多于一个函数,只要它们的参数不同即可。 换句话说,函数名可以被重载。不管你是否使用它,这种能力都要求在某些用户不信任其他用户的数据中调用函数时做一些预防措施,见第 10.3 节。当一个查询 被执行时,服务器将从数据类型和所提供的参数个数来决定要调用哪个 函数。重载也可用来模拟具有可变参数个数(最大个数有限)的函数。

在创建一个重载函数家族时,应该小心不要创建歧义。例如,给定函数:

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

对于test(1, 1.5)这样的输入就无法立刻清楚地知道 应该调用哪个函数。当前实现的解决规则在第 10 章 中有描述,但是设计一个依赖于这种行为的系统是不明智的。

一个具有单个组合类型参数的函数通常不应与该类型的任何属性(域) 重名。回想一下,attribute(table)被认为等效于 table.attribute。在出现“一个组合类型 上的函数”与“组合类型的一个属性”的情况下,将总是使用属性。 可以通过用模式限定该函数名(即 schema.func(table) )来覆盖这种选择,但是最好 不要选择有冲突的名称以避免此类问题。

另一种可能的冲突在于 variadic 和非 variadic 函数之间。例如,可以创建 foo(numeric)foo(VARIADIC numeric[])。 在这种情况下,对于提供了一个数字参数的调用(例如foo(10.1)) 就不清楚应该匹配哪一个函数。规则是使用在搜索路径中出现得较早的 函数,或者当两者都在同一个模式中时优先使用非 variadic 的那一个函数。

在重载 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 函数名称反映了很多种可能的习惯之一。