Para crear una función en el lenguaje PL/Tcl, utiliza la sintaxis estándar de CREATE FUNCTION:
CREATE FUNCTIONfuncname(argument-types) RETURNSreturn-typeAS $$ # cuerpo de la función PL/Tcl $$ LANGUAGE pltcl;
PL/TclU es lo mismo, excepto que el lenguaje debe especificarse como
pltclu.
El cuerpo de la función es simplemente un fragmento de script de Tcl.
Cuando se llama a la función, los valores de los argumentos se pasan al
script de Tcl como variables llamadas 1
... . El resultado se
devuelve desde el código de Tcl de la manera habitual, con una
sentencia nreturn. En un procedimiento, el valor de retorno
del código de Tcl es ignorado.
Por ejemplo, una función que devuelva el mayor de dos valores enteros podría definirse como:
CREATE FUNCTION tcl_max(integer, integer) RETURNS integer AS $$
if {$1 > $2} {return $1}
return $2
$$ LANGUAGE pltcl STRICT;
Ten en cuenta la cláusula STRICT, que nos evita tener
que pensar en valores de entrada null: si se pasa un valor null, la
función no se llamará en absoluto, sino que simplemente devolverá un
resultado null automáticamente.
En una función no estricta,
si el valor real de un argumento es null, la variable
$ correspondiente se establecerá en una cadena vacía.
Para detectar si un argumento particular es null, utiliza la función
nargisnull. Por ejemplo, supongamos que queremos que tcl_max
con un argumento null y uno no null devuelva el argumento
no null, en lugar de 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;
Como se muestra arriba,
para devolver un valor null desde una función PL/Tcl, ejecuta
return_null. Esto se puede hacer tanto si la
función es estricta como si no.
Los argumentos de tipo compuesto se pasan a la función como arrays de Tcl. Los nombres de los elementos del array son los nombres de los atributos del tipo compuesto. Si un atributo en la fila pasada tiene el valor null, no aparecerá en el array. Aquí tienes un ejemplo:
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;
Las funciones PL/Tcl también pueden devolver resultados de tipo compuesto. Para hacer esto, el código Tcl debe devolver una lista de pares nombre/valor de columna que coincidan con el tipo de resultado esperado. Cualquier nombre de columna omitido de la lista se devuelve como null, y se lanza un error si hay nombres de columna inesperados. Aquí tienes un ejemplo:
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;
Los argumentos de salida de los procedimientos se devuelven de la misma manera, por ejemplo:
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);
La lista de resultados se puede crear a partir de una representación en array de la
tupla deseada con el comando Tcl array get. Por ejemplo:
CREATE FUNCTION raise_pay(employee, delta int) RETURNS employee AS $$
set 1(salary) [expr {$1(salary) + $2}]
return [array get 1]
$$ LANGUAGE pltcl;
Las funciones PL/Tcl pueden devolver conjuntos. Para hacer esto, el código Tcl debe
llamar a return_next una vez por fila a devolver,
pasando el valor apropiado al devolver un tipo escalar,
o una lista de pares nombre/valor de columna al devolver un tipo compuesto.
Aquí tienes un ejemplo que devuelve un tipo escalar:
CREATE FUNCTION sequence(int, int) RETURNS SETOF int AS $$
for {set i $1} {$i < $2} {incr i} {
return_next $i
}
$$ LANGUAGE pltcl;
y aquí tienes uno que devuelve un tipo compuesto:
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;