受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发版本: devel

42.2. PL/Tcl 函数和参数 #

要用PL/Tcl语言创建函数,可使用标准的CREATE FUNCTION语法:

CREATE FUNCTION funcname (argument-types) RETURNS return-type AS $$
    # PL/Tcl function body
$$ LANGUAGE pltcl;

PL/TclU的写法相同,只是语言必须指定为pltclu

函数体就是一段 Tcl 脚本。调用函数时,参数值会作为名为1 ... n的变量传递给 Tcl 脚本。结果按通常方式通过return语句从 Tcl 代码中返回。对于过程,Tcl 代码的返回值会被忽略。

例如,一个返回两个整数值中较大值的函数可以定义为:

CREATE FUNCTION tcl_max(integer, integer) RETURNS integer AS $$
    if {$1 > $2} {return $1}
    return $2
$$ LANGUAGE pltcl STRICT;

注意STRICT子句,它让我们不必考虑空输入值:如果传入的是空值,函数根本不会被调用,而是会自动返回空结果。

在非严格函数中,如果某个参数的实际值为空,对应的$n变量会被设置为空串。要检测某个特定参数是否为空,可使用函数argisnull。例如,假设我们希望在tcl_max的两个参数中一个为空、一个非空时返回非空参数,而不是返回空值:

CREATE FUNCTION tcl_max(integer, integer) RETURNS integer AS $$
    if {[argisnull 1]} {
        if {[argisnull 2]} { return_null }
        return $2
    }
    if {[argisnull 2]} { return $1 }
    if {$1 > $2} {return $1}
    return $2
$$ LANGUAGE pltcl;

如上所示,要从 PL/Tcl 函数返回空值,请执行return_null。无论函数是否为严格函数,都可以这样做。

复合类型参数会作为 Tcl 数组传递给函数。数组元素名就是该复合类型的属性名。如果传入行中的某个属性为 NULL,它就不会出现在数组中。下面是一个示例:

CREATE TABLE employee (
    name text,
    salary integer,
    age integer
);

CREATE FUNCTION overpaid(employee) RETURNS boolean AS $$
    if {200000.0 < $1(salary)} {
        return "t"
    }
    if {$1(age) < 30 && 100000.0 < $1(salary)} {
        return "t"
    }
    return "f"
$$ LANGUAGE pltcl;

PL/Tcl 函数也可以返回复合类型结果。要做到这一点,Tcl 代码必须返回一个与预期结果类型匹配的“列名/值”对列表。凡是未在列表中出现的列名,都会作为空值返回;如果出现预期之外的列名,则会报错。下面是一个示例:

CREATE FUNCTION square_cube(in int, out squared int, out cubed int) AS $$
    return [list squared [expr {$1 * $1}] cubed [expr {$1 * $1 * $1}]]
$$ LANGUAGE pltcl;

过程的输出参数也按同样的方式返回,例如:

CREATE PROCEDURE tcl_triple(INOUT a integer, INOUT b integer) AS $$
    return [list a [expr {$1 * 3}] b [expr {$2 * 3}]]
$$ LANGUAGE pltcl;

CALL tcl_triple(5, 10);

Tip

可使用 Tcl 的array get命令,根据期望元组的数组表示构造结果列表。例如:

CREATE FUNCTION raise_pay(employee, delta int) RETURNS employee AS $$
    set 1(salary) [expr {$1(salary) + $2}]
    return [array get 1]
$$ LANGUAGE pltcl;

PL/Tcl 函数也可以返回集合。要做到这一点,Tcl 代码应当对每个要返回的行调用一次return_next:返回标量类型时传入适当的值,返回复合类型时传入“列名/值”对的列表。下面是返回标量类型的示例:

CREATE FUNCTION sequence(int, int) RETURNS SETOF int AS $$
    for {set i $1} {$i < $2} {incr i} {
        return_next $i
    }
$$ LANGUAGE pltcl;

下面是返回复合类型的示例:

CREATE FUNCTION table_of_squares(int, int) RETURNS TABLE (x int, x2 int) AS $$
    for {set i $1} {$i < $2} {incr i} {
        return_next [list x $i x2 [expr {$i * $i}]]
    }
$$ LANGUAGE pltcl;

提交更正

如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。