GKD-Base中Instead-Of触发器实现的关键技术
2008-07-24
作者:陈 浩, 廖 巍, 陈宏盛,
摘 要:兼容Oracle PL/SQL V2.3 语言规范,基于国产数据库管理系统" title="管理系统">管理系统GKD-Base" title="GKD-Base">GKD-Base内核与PL/SQL引擎,提出了Instead-Of视图触发器的编译存储和点火执行算法,并设计实现了Instead-Of 视图触发器编译及执行处理模块" title="处理模块">处理模块。从而在GKD-Base上实现了Instead-Of视图触发器机制,扩展了国产数据库GKD-Base功能。
关键词:PL/SQL引擎 Instead-Of触发器
GKD-Base是一个具有自主知识产权的数据库管理系统,经过十几年的发展和应用,该系统已经被证明是稳定可靠的。但是,随着应用需求向深度和广度的发展,GKD-Base在很多方面都暴露出了不足,如不支持过程式SQL语言、不支持存储过程和函数、缺少触发器功能等,这都为GKD-Base数据库管理系统的进一步推广应用带来了不小的障碍。
为此笔者开发了GKD-Base PL/SQL引擎,其兼容Oracle PL/SQLV2.3规范。进而在引擎的基础上实现了GKD-Base DML触发器功能[1]。但目前GKD-Base对于视图更新的支持还很不够,对于连接视图的更新有着十分严格的限制。国外数据库系统" title="数据库系统">数据库系统如Oracle[2]、SQL Server[3]、PostgreSQL[4]等都提供了所谓的Instead-Of视图触发器来支持视图更新。定义有Instead-Of触发器的视图被DML语句操作时,相应的DML语句不执行,而触发器体被执行,于是用户可以按照自己定义的语义修改定义视图的基本表,以达到修改视图的目的。因此,为了使GKD-Base适应应用需求的发展,在GKD-Base PL/SQL引擎的基础上实现了GKD-Base Instead-Of视图触发器功能[1]。
1 视图更新歧义问题
视图是虚拟的关系,数据库系统中只存储它的定义,不存储元组数据。一个视图可以看成一个临时关系,视图是产生这种临时关系的查询定义[5]。
由于视图是虚拟的关系,对视图的更新操作必须映射到对相应的基本表操作才能实现。完成视图更新后的数据库状态由视图定义导出一个新的视图状态,新的视图状态对应由原视图状态直接完成视图的更新操作。
如图1所示,u是关系数据库DB的视图v(DB)的更新操作,T(u)是对视图更新操作的变换,它作用到DB上产生新的数据库状态DB′、新的视图状态v(DB′)。正确的视图更新操作使得u(v(DB))= v(DB′)。但是对视图更新操作的变换T(u)并不总存在[6]。即使存在,也不总是惟一的。视图的更新存在固有的歧义性,仅有上面的语义是不够的。
并且,由于视图本身的歧义性和语义不完整性[7],无法对于有着集合操作符(如:UNION、MINUS等)、聚集函数(如:SUM、AVE等)和GROUP BY子句的视图更新提供支持。
2 Instead-Of触发器设计实现
2.1 PL/SQL引擎体系结构
根据PL/SQL语言兼有过程式语句和SQL语句的特点,GKD-Base PL/SQL引擎把过程式语句和SQL语句分开处理。为了降低引擎实现的复杂程度,从功能性的角度将整个引擎划分为前端编译器和后端解释执行器" title="执行器">执行器,每个处理模块尽量降低相互间的耦合程度。
前端编译器包括语言预处理、SQL语句分析、过程语句分析以及中间代码生成等功能。PL/SQL语句块输入后,由语言预处理功能分离成SQL语句和过程语句。对于SQL语句,由GKD-Base SQL引擎解析后,建立SQL语句结点,进行相应的变量绑定和语法检查,检查无误后产生语法树形式的中间代码。对于过程语句,将语句成分进行语法分析,在分析中把声明的变量和数据类型加入到名字空间和符号表中,同时产生语法树形式的中间代码。
后端解释执行器的功能就是对前端编译器生成的中间代码进行解释执行。因此在结构上,解释执行器与编译器对应,也有过程语句执行模块和SQL语句执行模块,过程语句解释执行器解释执行过程语句的中间代码,SQL命令则直接由SQL引擎执行。另外,解释器还包括例外处理模块,负责检查错误和报告错误[8]。
2.2 Instead-Of触发器设计
2.2.1触发器模型
GKD-Base DML触发器采用传统的ECA(Event-Condition-Action,事件—条件—动作)规则设计。与之类似的Instead-Of 视图触发器也采用了ECA规则。
为了适应触发器的具体情况,在GKD-Base中,Instead-Of 视图触发器扩展为一个四元组模型:Trigger:=
E(Event):激发Instead-Of 视图触发器的事件。这里主要是指操作视图的DML事件,包括Insert、 Delete和Update等。
C(Condition):定义触发器时指定的条件。是一个一元谓词表达式。
A(Action):当Event发生,并且Condition为真时,触发的动作。
S(Status):触发器有活跃和休眠两种状态,触发器处于活跃状态时,才可被激发。
2.2.2 触发器实现框架
触发器实现框架如图2所示。触发器类别判决器是在系统执行SQL语句之前,对SQL语句的操作对象进行判断,如果是对基本表操作,则启动DML触发器的监测功能;如果是对视图进行操作,则启动Instead-Of 视图触发器的监测功能。事件监视器是在有关的系统行为发生时,为各种预定的事件给触发器调度器发送信号。触发器调度器接收事件监视器的信号,从数据字典中获取该事件点火的所有触发器,并且按照特定的顺序排序,调用条件评价器检查各触发器的触发条件是否满足,若满足则由触发器调度器通知PL/SQL引擎解释执行该触发器的动作代码。条件评价器是用来检查触发条件是否满足的部件。对于语句级触发器,由于不存在触发条件子句,所以触发条件始终为真。对于行(元组)级触发器,条件评价器可以将其触发条件WHEN子句转换成一个PL/SQL语言的IF语句,然后由PL/SQL引擎实现触发器条件的计算。
2.3 Instead-Of触发器实现
2.3.1 触发器谓词以及new和old元组的设计
触发器谓词是指触发器内部用来标识激发触发器动作的DML语句的布尔变量,为:INSERTING、UPDATING、DELETING。其分别对应于PL/SQL程序中的三个布尔变量,它们在编译触发器时被加载到符号表中,在调用PL/SQL引擎执行触发器动作体之前,它们的值被准备好,供PL/SQL引擎取用。
NEW和OLD元组作为PL/SQL程序中的记录样式加载到符号表中,被编译器引用。其记录域与新旧元组对应的表的各个属性一一对应。在调用PL/SQL引擎执行触发器动作体之前,必须准备好NEW和OLD的值。但NEW和OLD元组是伪记录类型,不能完全按照记录的语法来访问[12]。这一点必须在编译时加入新的语义规则。
2.3.2 Instead-Of触发器的编译与存储
功能:编译触发器定义语句后,将触发器信息存储于数据字典中。
输入:一条用户输入的触发器定义语句。
输出:触发器数据字典的元组。
(1)判断当前事务是否存在,如果存在,则提交当前事务,并开始一个新事务;否则,直接开始一个新事务。
(2)用户权限检查。如果当前用户无权执行该操作,转(12);否则转(3)。
(3)检查触发表(视图)名及触发事件所涉及的属性是否存在。在GKD-Base的数据字典SYS.TABLES中查找,如果触发表或某个属性不存在,转(12);否则,转(4)。
(4)触发器名存在性检查。如果当前定义的触发器与以往定义的某个触发器重名,转(5);否则转(7)。
(5)如果声明语句中没有包含 OR REPLACE选项,转(12);否则,转(6)。
(6)如果触发表(视图)不一致,转(12);否则转(7)(触发表指定义了DML触发器或Instead-Of 视图触发器的基本表或视图)。
(7)检查定义触发器的合法性,DML触发器只能定义在基本表上,而Instead-Of视图触发器只能定义在视图上。检查合法,转(8),否则转(12)。
(8)调用PL/SQL引擎编译触发器动作体,并且将触发器的WHEN条件子句转换成一个IF语句,这个IF语句的真值部分包括了触发器动作体。如果触发器动作体中出现语法或语义错误,转(12);否则转(9)。
(9)在数据字典SYS.TRIGGERS表中插入一个新元组,填入此触发器的信息。如果出现磁盘I/O错误,转(12);否则转(10)。
(10)释放所占资源。
(11)提交当前事务,正常结束。
(12)回滚当前事务,报错退出。
2.3.3 Instead-Of视图触发器的点火执行
与DML触发器不同,Instead-Of 视图触发器在激发时,不必考虑各种触发器(如语句级前触发器和行级后触发器)之间的相互缠结。其点火算法也相对简单。 在触发事件当前的事务中构造一条SQL查询语句,从触发器数据字典表中获取与该触发事件相关的处于活跃状态的Instead-Of视图触发器元组。如果查询结果不为空,将触发器条件转换成一个PL/SQL语言的IF语句,并将触发事件当前所用到的元组值(新值和旧值)准备好,启动PL/SQL引擎,对触发器动作体的源代码进行解释执行。释放所占的资源,结束触发器调用。
3 系统应用实例
3.1实验数据
Rooms表如表1所示,Classes表如表2所示。在Classes表和Rooms表中Room_ID相等的连接条件上创建一个名为Classes_rooms的视图,进行连接运算。Classes_rooms视图如表3所示。
定义关于Classes_rooms 的Update语义:通过对Classes_rooms的Update操作,实现对一个班级某门课程占用教室的调整。通过Instead-Of触发器实现:如果修改了Classes_rooms的Dept和Course属性,那么就修改Classes基本表的相应属性,如果修改了Classes_rooms的Building和Room_Num属性,那么就修改Rooms基本表的相应属性。再适当调整两个基本表的Room_ID。
3.2 实验结果
执行UPDATE classes_rooms SET Dept=‘NUT’, course = 307 WHERE building=‘Buidling 7’ AND room_num = 201; 查询更新后的视图,观察Instead-Of触发器对视图的作用。
表4、表5、表6演示了本实验的结果。由结果可知,通过Instead-Of触发器,成功地对Classes_rooms视图进行了修改,将历史系101课的教室调整给了营养系307课程使用。通过以上应用实例验证了Instead-Of触发器带给数据库系统的视图修改功能。
本文参照Oracle PL/SQL V2.3 语言规范,在数据库管理系统GKD-Base 的PL/SQL引擎的基础上,给出了Instead-Of 视图触发器的编译存储和点火执行的相关算法,设计了Instead-Of视图触发器编译及执行处理模块,从而在实现DML 触发器的基础上实现了Instead-Of 视图触发器,并在实际中得到了验证。扩展了GKD-Base的功能,使其能够应用于更多的领域。
参考文献
1 Tom Portfolio. PL/SQL User′s Guide and Reference. Release 8.1.6. Oracle Corporation,1999
2 Ken Henderson. The Guru′s Guide to Transact-SQL. AddisonWesley Pub Co., 2000;2
3 PostgreSQL 7.4 Documentation.The PostgreSQL Global Development Group, 2003
4 景 宁. SQL查询处理与实现技术研究.长沙:国防科技大学.工学博士学位论文,1990;4
5 E.F.Codd. Recent Investigations in a Relational Database System. North-Holland Publishing Company,1974
6 刘念祖. 数据库系统中视图问题的研究. 计算机工程,1997;12
7 陈火旺. 程序设计语言——编译原理.北京:国防工业出版社,2000