《電子技術應用》
您所在的位置:首頁 > 嵌入式技術 > 業界動態 > GKD-Base PL/SQL存儲函數實現的關鍵技術研究

GKD-Base PL/SQL存儲函數實現的關鍵技術研究

2008-10-24
作者:高朝瑞 熊偉 陳宏盛  翟玉人

  摘 要: 介紹具有自主知識產權的某安全數據庫管理系統" title="管理系統">管理系統GKD-Base" title="GKD-Base">GKD-Base的PL/SQL引擎,基于該引擎研究GKD-Base存儲函數機制實現的關鍵技術。設計了函數管理器" title="管理器">管理器和執行狀態堆棧,通過語法樹表示存儲函數編譯后生成的中間代碼,并解決了中間代碼的執行問題。最后實現了IN、OUT、INOUT三種參數模式函數的參數傳遞機制。
  關鍵詞: 存儲函數 過程式SQL語言 PL/SQL 函數管理器 執行狀態堆棧


  GKD-Base是一個具有自主知識產權的安全數據庫管理系統。經過十幾年的發展和試點應用,已經證明該系統是穩定和安全可靠的。但是,隨著應用需求向深度和廣度的發展,GKD-Base在很多方面暴露出不足,如不支持過程式SQL語言、不支持存儲過程和函數、缺少觸發器功能,這都為GKD-Base數據庫管理系統的進一步推廣應用帶來了不小的障礙。由于目前數據庫管理系統產品大都支持過程式的SQL語言,如Oracle的PL/SQL、SQL Server的T-SQL、PostgreSQL的PL/pgSQL等,其中又以Oracle的PL/SQL使用最為廣泛。因此,為使GKD-Base適應應用需求的發展,滿足數據庫管理和開發人員的需求,筆者開發了GKD-Base PL/SQL引擎,進而在引擎的基礎上實現了GKD-Base存儲函數機制。GKD-Base PL/SQL引擎兼容了Oracle PL/SQL V2.3語言規范,可以使用變量、類型、表達式、條件和循環、過程和函數等過程式語言中的通用機制進行程序設計,同時也可以使用SQL 語句進行數據操作。
  存儲函數是獨立存在于表之外的數據庫對象,是由用戶按照存儲函數語言規范編寫的經過數據庫分析和編譯的PL/SQL程序,它有輸入/輸出參數和返回值,可以被其它應用程序調用。存儲函數可以避免重復編碼,具有更高的可靠性和效率,是數據庫管理系統的重要功能擴充。本文在介紹GKD-Base PL/SQL引擎設計框架的基礎上,重點探討GKD-Base存儲函數實現的關鍵技術。
1 GKD-Base PL/SQL引擎的體系結構
  GKD-Base采用客戶服務器結構,以多線程機制支持客戶訪問,登錄到數據庫的用戶實際上是運行數據庫管理系統映像的一個線程。GKD-Base支持TCP/IP協議,客戶可以在任何TCP/IP網絡和服務器建立連接訪問數據庫。GKD-Base API提供了用戶應用、實用程序和第三方開發工具三種接入數據庫的方式,并提供了兩個級別的接口,即GKD-Base內部接口GKD-API和GKD-Base ODBC Driver。GKD-API是用戶訪問數據庫的高效調用方式,用戶可利用GKD-API實現實時性要求較高的數據庫應用,起到比較理想的效果。GKD-Base ODBC Driver是GKD-Base開放連接的手段,符合ODBC擴展一級。在GKD-Base的ODBC驅動程序支持下,用戶可利用各種第三方開發工具,方便地開發GKD-Base數據庫應用程序。
  GKD-Base PL/SQL引擎應用模式如圖1。PL/SQL語句塊通過PL/SQL編譯器編譯成語法樹形式表示的中間代碼,中間代碼信息可以保存在DBMS的中間代碼庫中。客戶應用程序中的請求由GKD-Base預處理器分離成為過程語句部分和SQL命令部分。過程語句解釋執行器" title="執行器">執行器解釋執行過程語句的中間代碼,SQL命令則直接調用GKD-API執行。


  根據PL/SQL語言兼有過程式語句和SQL語句的特點,GKD-Base PL/SQL引擎把過程式語句和SQL語句分開處理。為了降低引擎實現的復雜程度,盡可能地從功能性的角度將整個引擎劃分為不同的處理模塊,每個處理模塊盡可能地降低相互間的耦合程度。其中最主要的劃分是將整個引擎劃分為前端編譯器和后端解釋執行器。
  前端編譯器包括語言預處理、SQL語句分析、過程語句分析以及中間代碼生成等功能。PL/SQL語句塊輸入后,由語言預處理功能分離成SQL語句和過程語句。對于SQL語句,由GKD-Base SQL引擎解析后,建立SQL語句結點,進行相應的變量綁定和語法檢查,檢查無誤后產生語法樹形式的中間代碼。對于過程語句,將語句成分進行語法分析,在分析中把聲明的變量和數據類型加入到符號表中,同時也產生語法樹形式的中間代碼。
  后端解釋執行器的功能就是對前端編譯器生成的中間代碼進行解釋執行。因此在結構上,解釋執行器與編譯器對應,也有過程語句執行模塊和SQL語句執行模塊。過程語句解釋執行器解釋執行過程語句的中間代碼,SQL命令則直接由SQL引擎執行。另外,解釋器還包括例外處理模塊,負責錯誤檢查和報告。
  符號表是一個包含程序中的變量、自定義類型和函數信息的數據庫,它是GKD-Base PL/SQL引擎的核心數據結構。它以一個關鍵字域(通常是一個符號的名字)為索引,一個關鍵字域的值對應于庫中的一條記錄。每條記錄,即數據庫的一個項目,都對應著一個符號的信息,如變量的類型或函數的返回值等。
2 GKD-Base PL/SQL過程與函數語言成分設計
  子程序" title="子程序">子程序把功能獨立并需要反復用到的代碼加以參數化處理,從而整合為一個命名模塊,在要使用這個模塊時就傳入具體參數值(如果需要)進行調用。與第三代語言中的子程序一樣,GKD-Base PL/SQL過程與函數是特定功能的邏輯抽象,由子程序定義和引用組成,可以分為過程和函數兩種類別。PL/SQL子程序可以分開編譯并存儲到數據庫中,用CREATE 語句建立,并成為模式對象的一部分。存儲過程/函數可以位于包結構中,包分為包聲明和包體實現部分。本地過程/函數在DECLARE 節中的最后部分進行,而作為存儲過程和存儲函數將存儲在數據庫中,它們是命名的PL/SQL塊。這樣它們在結構上也就沒有特別之處了。下面主要討論形參和實參的綁定設計。
  PL/SQL 函數中的參數說明帶有輸入和輸出描述,需要在編譯時刻進行處理,并對調用時的參數類型是否相容進行檢查。但在PL/SQL過程和函數的聲明中,限制CHAR、VARCHAR2參數的長度以及限制NUMBER的精度都是非法的。這是由于在調用一個函數時,實際參數的取值被傳遞進去,在函數內部通過使用形式參數來引用這些實際參數,不僅實際數值被傳遞進去,而且作為參數傳遞機制的一部分,對于這些變量的限制也被傳遞進去。例如:
  創建函數:
  CREATE OR REPLACE FUNCTION ParameterLength (p_Var1 IN OUT VARCHAR2)
  RETURN VARCHAR2 AS
  BEGIN
    p_Var1:=′This is an example′;
    RETURN p_Var1; 
  END ParameterLength;
  調用函數:
  DECLARE
  v_Variable1 VARCHAR (30);
  v_Variable2 VARCHAR (30);
  BEGIN
    v_Variable2:= ParameterLength (v_Variable1);
  END;
  上述調用將使p_Var1變量的最大長度為30(來自實參)。而如果將v_Variable1的長度定義成10,將產生錯誤。這個錯誤的產生不是過程設計不好,而是因為調用該過程的代碼發生了問題。值得注意的是:在過程定義中如果使用%TYPE作為形參類型的限制,而基準類型又是受限的,那么該限制將作用于形式參數而不是實際參數。
  在缺省參數值的處理方式上,即當調用時,沒有指明實際值時,就用缺省值。對使用缺省值的形式參數,通常需要把它們放到參數表的末尾,這樣無論使用位置標識法還是帶名標識法都可以。
3 GKD-Base存儲函數實現的關鍵技術
3.1函數管理器

  GKD-Base PL/SQL引擎對PL/SQL程序的解釋執行都通過一個內部統一的入口,解釋器把語法樹載入到入口內部的一個默認的主控函數,由這個函數驅動對其解釋執行。這樣處理的主要目的是為了兼容子程序的語法分析和保持解釋器運轉機制的一致性。因為子程序就是PL/SQL程序中命名的語句塊,用戶調用子程序時,PL/SQL引擎可以再次調用內部主控函數對其進行處理,并提交解釋器執行。
  PL/SQL子程序包括局部聲明子程序和存儲子程序。為了管理和調用局部聲明子程序,設計了函數管理器,如圖2。函數管理器內部定義了一系列數據結構來描述局部聲明子程序調用的各種屬性,提供各種宏調用來獲取局部聲明子程序調用的參數和返回值,并提供必要的支持函數。從某種角度看,函數管理器也是用來存放各種局部聲明函數和過程信息的“符號表”,因為在管理器中還包括對聲明子程序聲明和調用信息的存儲、查找等功能。函數管理器提供一種結構化的處理手段,以一種統一的方式實現對局部聲明子程序的調用。這種“統一”表現在:每個局部聲明子程序都在函數管理器中獲得一個識別號(Oid),這個識別號唯一標識該局部聲明子程序;函數管理器維持一份記錄表格,其中存放所有局部聲明子程序的識別號、子程序名、子程序地址、參數個數和返回值類型等信息,同時接口還提供相應的查找功能,源程序中的局部聲明子程序調用會被轉換成為子程序的識別號并通過該識別號查找得到子程序的詳細信息。


  所有局部聲明子程序都在函數管理器中進行注冊,存儲子程序并不在函數管理器中注冊,而是保存在數據庫中。對于一個子程序調用,首先根據子程序名到函數管理器中查找;如果沒有在函數管理器中找到再去查找數據庫,這樣就兼容了Oracle PL/SQL V2.3局部聲明子程序的定義優先于存儲子程序的規則。
3.2 執行狀態堆棧
  在GKD-Base PL/SQL引擎的解釋執行器中,設計了一個 “執行狀態”的數據結構,其中記載了存儲函數的執行狀態信息,如函數中的聲明變量、函數的參數個數、函數的參數類型、函數每個參數的值、函數的返回值等。解釋器中所有的解釋函數都擁有一個指針參數指向這個結構,需要在這些函數間傳遞的信息(包括全局變量信息)將被拷貝到這個結構。考慮到存儲函數是個單獨的PL/SQL語句塊層次,因此設計了執行狀態堆棧。在調用存儲函數前,對當前的現場進行保存,也就是將當前的執行狀態壓棧;在存儲函數調用結束之后恢復保存的現場,彈出當前執行狀態,回到上一層執行狀態繼續執行,如圖3。


3.3 存儲函數的創建和調用
  用戶創建的存儲函數經過編譯得到中間代碼并保存在GKD-Base的中間代碼庫中。函數調用時,根據函數名到GKD-Base的中間代碼庫中查找相應存儲函數的中間代碼對其解釋執行,最后得到返回值。GKD-Base存儲函數的創建和調用分別對應中間代碼的產生和執行過程。
  PL/SQL引擎對存儲函數的創建的具體處理過程如下:
  ①編譯器得到用戶創建的存儲函數;
  ②對用戶創建的存儲過程進行編譯,如果編譯通過則生成該存儲函數的語法樹;否則向用戶報告錯誤;
  ③將存儲函數中間代碼保存在中間代碼庫中;存儲函數的源代碼保存在GKD-Base的系統表中,如表1;
  ④向用戶返回消息。
  根據Oracle PL/SQL V2.3 語言規范,存儲函數調用本身不是一個語句,它只能作為其它語句的一部分。PL/SQL引擎對存儲函數的調用的具體過程如圖4:
  ①解釋器中語句鏈的解釋函數調用存儲函數的解釋函數;
  ②解釋器在執行存儲函數之前,對當前的現場進行保存,即將當前的執行狀態壓棧;
  ③到數據庫的中間代碼庫中找到存儲函數的語法樹,把存儲函數的語法樹掛在整個PL/SQL語句塊語法樹的過程調用節點上,并提交解釋器;
  ④解釋器執行存儲函數中間代碼;
  ⑤解釋器在存儲函數調用結束后,將返回值返回給調用它的語句,并恢復保存的現場,彈出當前執行狀態,回到上一層執行狀態繼續執行。


3.4 存儲函數的參數傳遞機制
  上述存儲函數調用過程中的一個主要難點就是實際參數和形式參數之間值的傳遞。與其它第三代語言一樣,用戶可以創建帶參數的PL/SQL存儲函數。這些參數可以通過值進行傳遞,也可以通過引用進行傳遞。
  GKD-Base PL/SQL引擎對存儲函數的形式參數的處理與對變量的處理是一致的,每個形式參數的屬性信息對應著符號表中的一條記錄,形式參數的名字信息保存在相應的名字堆棧層次內。如本文第三部分所述,存儲函數的語法樹也是由解釋器載入到一個內部默認的主控函數,由這個函數驅動對其解釋執行。解釋器內部的主控函數驅動存儲函數中所有變量的初始化,也驅動實際參數和形式參數之間值的傳遞。編譯器解析過程調用語句得到實際參數信息,首先判斷實際參數和形式參數的數據類型是否匹配,經過類型檢查后,如果實際參數是常量或普通變量,直接將實際參數的值拷貝給形式參數;如果實際參數是表達式,計算表達式的值傳給形式參數;如果存儲函數的形式參數個數大于解析得到的實際參數個數,二者之差為n,那么前面的形式參數取實際參數的值,后n個形式參數取語法樹中對應的缺省值。
  在Oracle PL/SQL V2.3中,存儲函數的形式參數有三種模式:IN、OUT或INOUT。當調用函數時,對IN參數,實際參數的值傳遞給過程,函數結束后,實際參數沒有被改變;對OUT參數,實際參數的任何值都被忽略,形式參數有一個NULL值,函數結束后,形式參數的內容賦給實際參數;對INOUT參數,實際參數的值傳遞給過程,函數結束后,形式參數的內容賦給實際參數。同時在存儲函數內部,對IN參數賦值和把OUT參數賦給局部變量都是非法操作。
  在GKD-Base PL/SQL引擎中實現存儲函數三種形式參數模式的關鍵是執行前后實際參數和形式參數的值的相互正確傳遞。在執行存儲函數中間代碼前,判斷每個形式參數的模式,如果參數模式是IN或INOUT,直接把實際參數的值傳遞給形式參數;如果模式是OUT,直接賦給形式參數一個初始的NULL值。對函數執行體內的賦值語句進行判斷檢查,如果賦值目標是IN參數或把OUT參數賦給其它變量,都報告相應的執行錯誤。函數執行結束后,解釋器彈出當前執行狀態,回到上一層執行狀態繼續執行。對IN參數,實際參數直接取其本身的值,即實際參數沒有改變;對OUT參數和INOUT參數,根據執行前形式參數和實際參數的對應關系,用執行完畢后的形式參數的值替代原來實際參數的值,即執行完后形式參數的內容賦給實際參數。
  PL/SQL 集成了一般過程式語言和說明性SQL 語言的特點,簡潔、高效,而其內容卻十分豐富。這也從一個方面說明了作為過程式數據庫編程語言,在考慮到底層數據庫功能時所面臨的各種選擇的艱難。PL/SQL 語言的某些功能將隨著ORACLE 數據庫的發展而繼續增強,但是該語言的結構是基本穩定的。本文參照Oracle PL/SQL V2.3 語言規范,在某安全數據庫管理系統GKD-Base上開發了PL/SQL引擎作為該系統的重要擴充,并在該引擎基礎上實現了GKD-Base存儲函數機制,提供給用戶一種高效率的編程手段,增強了GKD-Base的功能。希望本文實現的PL/SQL引擎能對國產數據庫的開發起到借鑒作用。當然PL/SQL 語言內容十分豐富,本文不可能涉及到每一個設計細節,PL/SQL 還在進一步發展,值得繼續關注。
  為了進一步擴展GKD-Base在安全保密領域的應用前景,筆者將在對GKD-Base本身進一步完善的同時,繼續對GKD-Base PL/SQL引擎進行完善和改進。一方面在功能上實現封裝函數和過程的包;另一方面,在性能上對原有GKD-Base PL/SQL引擎進行優化以提高編譯和執行效率。
參考文獻
1 Ken Henderson. The Guru′s Guide to Transact-SQL. AddisonWesley PuB Co., 2000
2 PostgreSQL 7.4 Documentation.The PostgreSQL GloBal Development Group, 2003
3 Kenneth C.Louden著,馮博琴譯.編譯原理及實踐.北京:機械工業出版社,2000
4 Hector Garcia-Molina,Jeffrey D. Ullman,Jennifer Widom著.楊東青,唐世渭,徐其鈞譯. 數據庫系統實現. 北京:機械工業出版社,2001
5 Levine,J.R.,lex與yacc(第二版).北京:機械工業出版社,2003

本站內容除特別聲明的原創文章之外,轉載內容只為傳遞更多信息,并不代表本網站贊同其觀點。轉載的所有的文章、圖片、音/視頻文件等資料的版權歸版權所有權人所有。本站采用的非本站原創文章及圖片等內容無法一一聯系確認版權者。如涉及作品內容、版權和其它問題,請及時通過電子郵件或電話通知我們,以便迅速采取適當措施,避免給雙方造成不必要的經濟損失。聯系電話:010-82306118;郵箱:[email protected]
主站蜘蛛池模板: 亚洲免费在线视频 | 中文国产成人精品久久一 | 黄黄的网站在线观看 | 日本天堂网址 | 亚洲一区二区三区中文字幕 | 在线观看国产精品日本不卡网 | 国产成人精选免费视频 | 日韩精品一区二三区中文 | 日韩美女免费线视频 | 亚洲欧美午夜 | 在线看欧美日韩中文字幕 | 亚洲福利视频精选在线视频 | 亚洲日本综合 | 久久久亚洲精品国产 | 免费国产在线观看 | 91精品国产91久久久久 | 欧美日本色 | 亚洲精品中文字幕在线 | 日韩不卡一区二区 | 精品无码一区在线观看 | 国产一级做a爰片在线 | 国产成人永久免费视频 | 久久99国产精品久久 | 久久久免费视频播放 | 在线视频久草 | 2017天天爽夜夜爽精品视频 | 久久性妇女精品免费 | 国产美女野外做爰 | 最新欧美精品一区二区三区不卡 | 中文字幕在线不卡 | 欧美色成人tv在线播放 | 亚洲日本高清成人aⅴ片 | 久久精品国产99国产精品 | 美女一级毛片视频 | 国产亚洲欧美日韩在线观看一区二区 | 精品国产成人a区在线观看 精品国产成人a在线观看 | 欧美一级第一免费高清 | 喷潮白浆直流在线播放 | 亚洲美女黄视频 | 日本欧美不卡一区二区三区在线 | 亚洲人成网站观看在线播放 |