亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 數據庫 > PostgreSQL > 正文

PostgreSQL7.0手冊-用戶手冊-11. PL/Tcl - TCL 過程語言

2019-09-08 23:33:10
字體:
來源:轉載
供稿:網友
第十一章. PL/Tcl - TCL 過程語言
內容 
概述 
描述 
PL/Tcl 是一種用于 Postgres 數據庫系統的可裝載的過程化語言,它讓我們可以用 Tcl 語言來創建函數和觸發器過程. 
這個軟件包最初是由 Jan Wieck 開發的. 
概述
PL/Tcl 提供 C 語言里面函數開發者所擁有的大多數功能,只有一點點限制除外. 
好的限制是,所有東西都是在一個安全的 Tcl 解釋器里面運行的.除了有限的安全的 Tcl 命令集外,只有很少的幾個命令可以用于跨過 SPI 訪問數據庫以及通過 elog() 生成錯誤信息.不象 C 那樣,(Tcl)沒有辦法訪問數據庫后端內部或者獲得 OS 級的 Postgres 用戶 ID 的權限.因此,任何非特權的數據庫用戶都可以被允許使用這種語言. 

另外的(內部施加)的限制是 Tcl 過程不能創建用于新數據庫類型的輸入/輸出函數. 

如果在安裝過程中的配置階段打開了 Tcl/Tk 支持,那么用于 PL/Tcl 控制器的共享對象自動制作和安裝在 Postgres 庫目錄里面.

--------------------------------------------------------------------------------

描述
Postgres 函數和 Tcl 過程名
在 Postgres 里,一個函數名可以用于不同的函數,只要這些函數的參數個數和類型不同即可.這一點將與 Tcl 過程名(命名規則)沖突.為了在 PL/Tcl 里提供同樣的方便,在內部,Tcl 過程名包含該過程在 pg_proc 里的行對象標識(OID)做為它們的名字的一部分.因此,不同參數類型的 Postgres 函數對 Tcl 也是不同的.
用 PL/Tcl 定義函數
要用 PL/Tcl 語言創建一個函數,使用已知的語法 
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';
PL/Tcl 里的全局量
有時候(尤其是在使用下面描述的 SPI 函數的時候),在兩個過程之間保存一些狀態數據和非常有用的.所有在一個后端運行的 PL/Tcl 過程共享同一個安全 Tcl 解釋器.為了避免一些 PL/Tcl 過程的副作用,每個過程可以通過 upvar 命令訪問一個數組.此變量的全局名稱是過程的內部名稱,其局部名稱是 GD.
PL/Tcl 里的觸發器過程
在 Postgres 里的觸發器過程定義為沒有參數并且返回類型是opaque.在 PL/Tcl 語言里也是這樣. 
觸發器管理器傳遞給過程體的信息是通過下面變量傳遞的: 
$TG_name 
CREATE TRIGGER 語句里的觸發器名稱. 
$TG_relid 
導致觸發器被調用的表的對象標識. 
$TG_relatts 
以一個空表元素為前綴的表里的字段名稱的 Tcl 數組.所以用 lsearch Tcl 命令在數組里查找元素名稱時,返回的從1開始計數的正整數與該字段在 pg_attribute 系統表里該字段的序號一樣. 
$TG_when 
由觸發器調用事件決定的字符串 BEFORE 或 AFTER . 
$TG_level 
由觸發器調用事件決定的字符串 ROW 或 STATEMENT?。?
$TG_op 
由觸發器調用事件決定的字符串 INSERT,UPDATE 或 DELETE . 
$NEW 
在 INSERT/UPDATE 時一個包含表的新行的數組或在 DELETE 時的一個空數組. 
$OLD 
在 UPDATE/DELETE 時一個包含表的舊行的數組或在 INSERT 時的一個空數組. 
$GD 
前面所述的全局狀態數據數組. 
  
$args 
如同在 CREATE TRIGGER 語句里給出的參數一樣的參數表.這些參數在過程體里可以通過 $1 ... $n 來訪問. 
觸發器過程返回的值是字符串 OK 或 SKIP 之一,或者一個象 'array get' Tcl 命令返回的數組.如果返回值是 OK,觸發觸發器的操作(INSERT/UPDATE/DELETE)將會發生.顯然,SKIP 告訴觸發器管理器隱式的忽略操作.從 'array get' 來的數組告訴 PL/Tcl 返回一個修改后的行給觸發器管理器,該行將代替在 $NEW?。ㄖ辉凇NSERT/UPDATE 中)中給出的行.當然,這些只有在觸發器是 BEFORE 和 FOR EACH ROW 時才有意義. 
下面是一個小的觸發器過程的例子,它強制表內的一個整數值對行的更新次數進行跟蹤.對插入的新行,該值初始化為 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');
從 PL/Tcl 里訪問數據庫
我們可以用下面的命令從一個 PL/Tcl 過程體里面訪問數據庫: 
  
elog level msg 
產生一條日志信息.可能的級別是 NOTICE,WARN,ERROR,FATAL,DEBUG 和 NOIND,與用于 C 函數的 elog() 一樣. 
quote string 
復制所有出現的單引號和反斜杠字符.當賦予 spi_exec 或 spi_prepare?。ú挥糜凇pi_execp 使用的數組)的查詢字符串里使用了變量時就要使用這個命令.想象下面的查詢字符串 
      "SELECT '$val' AS ret"
如果 Tcl 變量 val 實際包含 "doesn't".這樣會導致最終的查詢字符串結果 
      "SELECT 'doesn't' AS ret"
這個字符串在 spi_exec 或 spi_prepare 里將導致一個分析錯誤.它將包括 
      "SELECT 'doesn''t' AS ret"
并且不得不寫成 
      "SELECT '[ quote $val ]' AS ret"
spi_exec ?-count n? ?-array name? query ?loop-body? 
  
調用 分析器/規劃器(調度器)/優化器/執行器運行查詢.可選的 -count 值告訴 spi_exec 該查詢可以處理的最大行數. 
  
  
  
  

如果查詢是一個 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 里的行數. 
spi_prepare query typelist 
  
為后面執行準備并且保存一個查詢規劃.這里與 C 級別的 SPI_prepare 有一些小區別,就是該規劃將自動拷貝到頂級存儲器環境.因此,目前沒有辦法準備一個規劃而不存儲它. 
  
  
  
  

如果查詢引用了參數,類型名必須做為 Tcl 數組給出.從 spi_prepare 返回的值是一個查詢 ID,該 ID 將被后繼的 spi_execp 調用使用.參閱 spi_execp 中的例子. 
  

spi_exec ?-count n? ?-arrayname? ?-nulls.string? query ?value-list? ?loop-body? 
  
代入參數執行一個來自 spi_prepare 的規劃.可選的 -count 數值告訴 spi_execp 可以被該查詢處理的最大行數. 
可選用于 -nulls 的值是一個空格字符串,并且 'n' 字符告訴 spi_execp 哪一個數值是 NULL.如果給出該值,它必須包含數值個數的確切長度. 
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 對常用的東西有一個特殊的支持.它識別兩個魔數表,pltcl_modules 和 pltcl_modfuncs.如果它們存在,模塊 'unknown' 在創建以后馬上裝載入解釋器.當調用一個未知的 Tcl 過程時,未知的 proc 馬上檢查該過程是否在其中一個模塊中定義了.如果的確定義了,該模塊按要求裝載進來.要打開這個特性,PL/Tcl 調用管理器必須帶著 -DPLTCL_UNKNOWN_SUPPORT 設置編譯. 
  
  
  
  

在 PL/Tcl 源文件的模塊子目錄里有一些維護這些表的腳本,包括在最初必須安裝的未知模塊的源文件.


--------------------------------------------------------------------------------
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品自产拍在线观看| 日韩专区中文字幕| 亚洲欧美激情另类校园| 亚洲精品ady| 国产经典一区二区| 91视频国产一区| 性日韩欧美在线视频| 国产婷婷色综合av蜜臀av| 亚洲免费人成在线视频观看| 欧美日韩不卡合集视频| 日韩在线视频免费观看高清中文| 欧美激情久久久久久| 欧美激情中文字幕在线| 日韩激情片免费| 国产精品视频自拍| 国产精品电影久久久久电影网| 69国产精品成人在线播放| 亚洲第一精品夜夜躁人人躁| 国产又爽又黄的激情精品视频| 日韩av网址在线| 国产一区香蕉久久| 黑人巨大精品欧美一区二区免费| 日韩在线视频一区| 亚洲黄一区二区| 午夜精品一区二区三区在线视| 一本色道久久综合狠狠躁篇怎么玩| 亚洲自拍小视频| 欧美理论电影在线观看| 国产精品免费一区| 欧洲精品毛片网站| 亚洲女同性videos| 久久亚洲国产成人| 亚洲精品国产品国语在线| 亚洲第一精品电影| 最近免费中文字幕视频2019| 国产精品一区二区久久久| 欧美午夜www高清视频| 久久久久久中文字幕| 久久久人成影片一区二区三区观看| 2019中文字幕在线| 国产精品自拍小视频| 国产精品久久av| 91在线精品视频| 国产成人激情视频| 国产精品欧美日韩久久| 国产成人一区二| 亚洲欧美激情在线视频| 国产精品视频久久久久| 国产一区私人高清影院| 欧美日本高清视频| 亚洲成人av在线| 国产69精品99久久久久久宅男| 欧美电影在线播放| 久久69精品久久久久久国产越南| 久久人人97超碰精品888| 91精品国产精品| 日韩av电影在线播放| 亚洲天堂日韩电影| 欧美激情啊啊啊| 国产999精品久久久影片官网| 国产日韩在线看片| …久久精品99久久香蕉国产| 热久久99这里有精品| 国产精品男人爽免费视频1| 国产精品视频免费在线观看| 久久精品色欧美aⅴ一区二区| 成人在线免费观看视视频| 日韩免费不卡av| 午夜欧美大片免费观看| 中文字幕国产日韩| 日韩电影免费观看中文字幕| 久久久国产精品视频| 国产精品视频久久久| 91精品视频播放| 久久久久久午夜| 日韩精品亚洲视频| 久久国产精品久久久久久久久久| 韩国三级电影久久久久久| 亚洲欧美精品一区| 亚洲国产成人91精品| 国产成人午夜视频网址| 理论片在线不卡免费观看| 亚洲影视九九影院在线观看| 国产精品美女呻吟| 人九九综合九九宗合| 欧美精品精品精品精品免费| 亚洲最新视频在线| 国产一区二区三区高清在线观看| 欧美性jizz18性欧美| 久久天天躁狠狠躁老女人| 亚洲人成电影网站色xx| 国产一区二区免费| 一本色道久久综合狠狠躁篇的优点| 欧美性受xxxx白人性爽| 国产精品激情av电影在线观看| 国产成人在线一区| 日本久久久久久| 精品香蕉一区二区三区| 日韩中文字幕在线免费观看| 国产成人免费av| 亚洲免费视频网站| 中文字幕不卡av| 欧美最猛性xxxxx免费| 色婷婷综合久久久久中文字幕1| 久久综合久久美利坚合众国| 久久久久久久电影一区| 97avcom| 国产美女精品视频免费观看| 国产精品美女999| 911国产网站尤物在线观看| 亚洲人免费视频| 久久久www成人免费精品张筱雨| 国产在线久久久| 奇米成人av国产一区二区三区| 免费成人高清视频| 亚洲毛片在线看| 美女久久久久久久| 国产剧情久久久久久| 欧亚精品中文字幕| 国产精品久久久久久久av大片| 亚洲香蕉在线观看| 亚洲精品99久久久久| 欧美日韩国产精品一区二区不卡中文| 国产精品亚洲一区二区三区| 欧美在线不卡区| 久久综合伊人77777尤物| 97视频在线观看视频免费视频| 91久久夜色精品国产网站| 久久久久九九九九| 国产欧美在线播放| 亚洲视频电影图片偷拍一区| 国产成人精品午夜| 亚洲日本欧美日韩高观看| 欧美午夜无遮挡| 按摩亚洲人久久| 色偷偷av亚洲男人的天堂| 久久久人成影片一区二区三区观看| 91精品视频在线| 欧美激情第1页| 日韩美女主播视频| 欧美一区二区视频97| 久久精品最新地址| 中文字幕亚洲欧美日韩在线不卡| 高清欧美电影在线| 日韩精品在线观看一区二区| 亚洲人成网站色ww在线| 日本精品性网站在线观看| 亚洲男人的天堂在线| 亚洲精品免费av| 亚洲新中文字幕| 97国产一区二区精品久久呦| 日韩免费观看av| 中文日韩在线观看| 国产成人一区二区三区小说| 亚洲自拍小视频免费观看| 国产精品久久久久久久久久久久久久| 欧美国产中文字幕| 搡老女人一区二区三区视频tv| 日韩美女在线播放| 中文综合在线观看| 亚洲国产精久久久久久| 国产欧美一区二区三区久久| 中文字幕亚洲欧美日韩高清| 一道本无吗dⅴd在线播放一区|