37.5. 函数重载

可以用同样的 SQL 名称定义多于一个函数,只要它们的参数不同即可。 换句话说,函数名可以被重载。当一个查询 被执行时,服务器将从数据类型和所提供的参数个数来决定要调用哪个 函数。重载也可用来模拟具有可变参数个数(最大个数有限)的函数。

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

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