42.2. Функции на PL/Tcl и их аргументы #
Чтобы создать функцию на языке PL/Tcl, используйте стандартный синтаксис CREATE FUNCTION:
CREATE FUNCTIONимя_функции
(типы_аргументов
) RETURNSтип_результата
AS $$ # Тело функции на PL/Tcl $$ LANGUAGE pltcl;
С PL/TclU команда та же, но в качестве языка должно быть указано pltclu
.
Тело функции содержит просто скрипт на Tcl. Когда вызывается функция, значения аргументов передаются скрипту Tcl в виде переменных с именами 1
...
. Результат из кода Tcl возвращается как обычно, оператором n
return
. В процедуре значение, возвращаемое из кода Tcl, игнорируется.
Например, функцию, возвращающую большее из двух целых чисел, можно определить так:
CREATE FUNCTION tcl_max(integer, integer) RETURNS integer AS $$ if {$1 > $2} {return $1} return $2 $$ LANGUAGE pltcl STRICT;
Обратите внимание на предложение STRICT
, которое избавляет нас от необходимости думать о входящих значениях NULL: если при вызове передаётся значение NULL, функция не будет выполняться вовсе, будет сразу возвращён результат NULL.
В нестрогой функции, если фактическое значение аргумента — NULL, соответствующей переменной $
будет присвоена пустая строка. Чтобы определить, был ли передан NULL в определённом аргументе, используйте функцию n
argisnull
. Например, предположим, что нам нужна функция tcl_max
, которая с одним аргументом NULL и вторым аргументом не NULL должна возвращать не NULL, а второй аргумент:
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;
Как показано выше, чтобы вернуть значение NULL из функции 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 должен вернуть список пар имя/значение столбца, соответствующий ожидаемому типу результата. Столбцы, имена которых в этом списке отсутствуют, получат значения NULL, а если в списке указано имя несуществующего столбца, возникнет ошибка. Например:
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);
Подсказка
Список результатов можно создать из желаемого кортежа, представленного в виде массива, с помощью команды array get
языка Tcl. Например:
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;