CREATE FUNCTION funcname argument-types) RETURNS return-type AS ' # PL/Tcl function body ' LANGUAGE 'pltcl';當在一個查詢裡面調用這個函數,參數是作為變數 $1 ... $n 傳遞給 Tcl 程序語言體的。所以一個簡單的返回兩個 int4 值的最大值函數可以這樣創建:
CREATE FUNCTION tcl_max (int4, int4) RETURNS int4 AS '
if {$1 > $2} {return $1}
return $2
' LANGUAGE 'pltcl';
復合型態參數是作為 Tcl 數組賦予程序的。數組的元素名稱就是復合型態的字段名稱。如果一個實際行的字段是一個
NULL 值,它將不在數組刈艴現!這裡是一個用 PL/Tcl 定義 overpaid_2 函數的例子(本例可以在舊的Postgres
文擋中找到)
CREATE FUNCTION overpaid_2 (EMP) RETURNS bool AS '
if {200000.0 < $1(salary)} {
return "t"
}
if {$1(age) < 30 && 100000.0 < $1(salary)} {
return "t"
}
return "f"
' LANGUAGE 'pltcl';
下面是一個小的觸發器程序的例子,它強制表內的一個整數值對行的更新次數進行跟蹤。對插入的新行,該值初始化為 0 並且在每次更新操作刈莨一:
CREATE FUNCTION trigfunc_modcount() RETURNS OPAQUE AS '
switch $TG_op {
INSERT {
set NEW($1) 0
}
UPDATE {
set NEW($1) $OLD($1)
incr NEW($1)
}
default {
return OK
}
}
return [array get NEW]
' LANGUAGE 'pltcl';
CREATE TABLE mytab (num int4, modcnt int4, desc text);
(譯注:desc 在6.5以上版本裡面是保留字,應該改成 describe 之類的東西。)
CREATE TRIGGER trig_mytab_modcount BEFORE INSERT OR UPDATE ON mytab
FOR EACH ROW EXECUTE PROCEDURE trigfunc_modcount('modcnt');
"SELECT '$val' AS ret"
"SELECT 'doesn't' AS ret"
"SELECT 'doesn''t' AS ret"
"SELECT '[ quote $val ]' AS ret"
如果查詢是一個 SELECT 語句並且給出了可選的循環體(一個 Tcl 命令的語句體,像一個 foreach 命令),它就會計算每個選擇的行並且如期望的那樣繼續/中斷。選擇的字段的值被放到命名為列名稱的變數裡面去了。所以一個
spi_exec "SELECT count(*) AS cnt FROM pg_proc"將把變數 $cnt 置為 pg_proc 系統表裡的行數。如果給出了可選的 -array ,列/字段的值將保存在相關的名為 'name' 的數組裡,而不是分離的變數。
spi_exec -array C "SELECT * FROM pg_class" {
elog DEBUG "have table $C(relname)"
}
將為 pg_class 的每一行列印一個 DEBUG 日誌資訊。spi_exec 返回的值是查詢涉及到的保存在全局變數
SPI_processed 裡的行數。
如果查詢引用了參數,型態名必須做為 Tcl 數組給出。從 spi_prepare 返回的值是一個查詢
ID,該 ID 將被後繼的 spi_execp 調用使用。參閱 spi_execp 中的例子。
queryid 是 spi_prepare 調用返回的 ID。(譯注:query?)
如果有一個型態列表給予了 spi_prepare,必須在查詢後面給 spi_execp 一個相同長度的 Tcl 數值列表(數組)。如果 spi_prepare 裡的型態表是空的,此參數必須忽略。
如果查詢是一個 SELECT 語句,有與 spi_exec 裡描述的循環體和用於所選的字段的變數有一樣的現像。
這裡是一個使用準備好了的規劃的 PL/Tcl 函數例子:
CREATE FUNCTION t1_count(int4, int4) RETURNS int4 AS '
if {![ info exists GD(plan) ]} {
# prepare the saved plan on the first call
set GD(plan) [ spi_prepare \\
"SELECT count(*) AS cnt FROM t1 WHERE num >= \\$1 AND num <= \\$2" \\
int4 ]
}
spi_execp -count 1 $GD(plan) [ list $1 $2 ]
return $cnt
' LANGUAGE 'pltcl';
注意創建函數時每個 Tcl 會看到的反斜杠必須寫雙份,因為在 CREATE FUNCTION
時主分析器也處理反斜杠。在給予 spi_prepare 的查詢字符串裡面應該是真正的標識參數位置的美圓符號,而不應讓第一次函數調用給出的值把
$1 給替換掉。
在 PL/Tcl 源文件的模組子目錄裡有一些維護這些表的腳本,包括在最初必須安裝的未知模組的源文件。