Document not found! Please try again

deriving triggers from uml/ocl specification - Springer Link

5 downloads 8137 Views 1MB Size Report
t Mohammad 8adawy, Dept. of Computer Science & Engineering, Faculty of Electrical ... information system is very vulnerable to integrity violations because it lacks strict .... follows: EMP(id,lastname,firstname,job,supervisor,salary,bonus,dept).
DERIVING TRIGGERS FROM UML/OCL SPECIFICATION" Mohammad Badawy and Karel Richtat 1. INTRODUCTION

The tenn integrity is used to refer to the accuracy or correctness of the data in a database. In other words, integrity involves ensuring that the data stored in the database are in any time correct. The database management system needs to be aware of certain rules that users must not violate. Those rules are to be specified in some suitable language, and have to be maintained in the data catalogue l . Integrity enforcement can be divided into two categories - static and dynamic. Static integrity enforcement is the task of ensuring that the data in a database are in a legal state. Dynamic integrity enforcement is the task of ensuring that a user transaction applied to a legal database state leads to a new state, which is also legal. The common rationale of research in this area is to centralize the management of data integrity. One possible solution of this problem is to extract the data integrity management from application programs and bringing it into an ad-hoc component, which may be incorporated into the active database management system 2 • The specification of what data are semantically correct constitutes one of the most important tasks in the database design process3• 4. In this process, data correctness requirements are gathered from users, business rules, and applications developers, and are translated into integrity constraint specifications. An active database management system continually monitors the database state and reacts spontaneously when predefined events occur. Functionally, an active database management system monitors conditions triggered by events representing database events

t

This work has been partially supported by the research program no. MSM 212300014 "Research in the Area of Information Technologies and Communications" of the Czech Technical University in Prague (sponsored by the Ministry of Education, Youth and Sports of the Czech Republic. Mohammad 8adawy, Dept. of Computer Science & Engineering, Faculty of Electrical Engineering, CTU in Prague, Karlovo nJm. 13, 121 35 Prague 2, Czech Republic, [email protected]_._Karel Richta, Dept. of Computer Science & Engineering, Faculty of Electrical Engineering, CTU in Prague, Karlovo nJm. 13, 121 35 Prague 2, Czech Republic, also Dept. of Software Engineering, Faculty of Mathematics & Physics, Charles University, Prague I, Malostranske nJm. 25, 118 00, Czech Republic, [email protected]

Information Systems Development: Advances in Methodologies, Components, and Management

Edited by Kirikova et ai., Kluwer AcademiclPIenum Publishers, 2002

305

M. BADAWY AND K. RICHTA

or non-database events (e.g. hardware failure); and if the condition is satisfied (evaluates to true), the action is executed6 • Active databases are taking a prominent role in commercial database applications 7,8, 9,10. With client/server solutions, applications are being developed by small, autonomous groups of developers with narrow views of the overall enterprise; the enterprise information system is very vulnerable to integrity violations because it lacks strict enforcement of the enterprise business rules 2• An active database management system should support constraints as well as event-driven application logic. Triggers that run automatically when certain events occur in the database are used to enforce database rules and to actively change datall . Triggers have a very low impact on the performance of server, and are often used to enhance applications that have to do a lot of cascading operations on other objects 12 • Triggers provide a very powerful and flexible means to realize effective constraint enforcing mechanismss. On the other hand the trigger approach is not yet well based. Triggers have limitations and pitfalls you should be aware of. Otherwise trigger systems can do what they want and not what the user wants. The goal of this paper is to give the rules for implementing triggers from UMLlOCL integrity constraint specifications. These rules are independent of any particular commercial database. A comparison of advantages of declarative constraints and triggers is also discussed. The text is structured as follows: Section 2 discusses the relative advantages of constraints and triggers. In Section 3, we give the trigger syntax. Section 4 gives some rules used to derive triggers from integrity constraint specifications, which are discussed in Section 5. An applicable example is given in Section 6, and finally, Section 7 gives the conclusions.

2. INTEGRITY CONSTRAINTS AND TRIGGERS The database engine has to provide two ways of enforcing data integrity - declarative constraints and procedural constraints (triggers). Declarative constraints should be used in lieu of triggers whenever possible. Several triggers may be required to enforce one declarative constraint; even then, the system has no way of guaranteeing the validity of the constraint in all cases2 • Consider the database load utilities in which the database checks the declarative constraints against the loaded data before it can be accessed. There is no way to determine which triggers should be checked since triggers are also used for transitional constraints and for event-driven application logic. This behavior also applies when constraints and triggers are added to a database with pre-existing data. The declarative constraints provided by most relational systems are defined in SQL92 (the same constraints are defined in SQL: 1999) to support only a small, although useful, set of static constraints that define the acceptable states of the value in the database. They do support only a limited subset of transitional constraints that restrict the way in which the database value can change from one state to the next. They do not support event-driven invocation of application and business logic. Hence, triggers are required to enhance the declarative constraint constructs and to capture application specific business rules. Triggers provide a procedural means for defining implicit activity during database modifications. They are used to support event-driven invocation of application logic, which can be tightly integrated with a modification and executed in the database engine by specifying a trigger on the base table of the modification. Triggers

307

DERIVING TRIGGERS FROM UMUOCL SPECIFICATION

should not be used as a replacement for declarative constraints. However, they extend the constraint logic with transitional constraints, data conditioning capabilities, exception handling, and user defined repairing actions 2. In summary, there are advantages to using both declarative constraints and procedural triggers, and both types of constructs are available in many commercial systems. IUs not feasible to expect applications providers to either migrate their existing applications to use only triggers or partition the tables in their database according to the type of constraints and triggers that are required. It is therefore imperative to define and understand the interaction of declarative constraints and triggers2.

3. TRIGGER SYNTAX SQL: 1999 13 provides the concept of triggers. A trigger is a procedure that is automatically invoked by the DBMS in response to specified database events. Triggers can be viewed as event-condition-action (ECA) rules that allow users to implement application logic within the DBMS. Triggers can be used to monitor modifications of the database, to automatically propagate database modifications, to support alerts, or to enforce integrity constraints5 • A trigger in SQL: 1999 has the following components: • • • • • •

A unique name, which identifies the trigger within the database, A triggering event, which are for our purposes INSERT, DELETE, or UPDATE on a database table, Ail activation time, which is BEFORE or AFTER executing the triggering events (it specifies when the trigger should be fired), A trigger granularity, which is FOR EACH ROW or FOR EACH STATEMENT, A trigger condition, which can be any valid SQL condition involving complex queries (The WHEN clause contains the violating condition), A triggered action, which can be any valid sequence of statements.

A trigger is implicitly activated whenever the specified event occurs. Thus, the database can react to changes made by applications or ad-hoc users. Several triggers may refer to the same event.

4. INTEGRITY CONSTRAINTS SPECIFICATION Typically, an integrity constraint can be formulated in such a way that all qualified rows from a table or a combination of tables have to satisfy a condition. We will use Object Constraint Language (OCL)14, IS, 16 for integrity constraints specification. Let us suppose that we have objects of a type T. The constraint specification in OCL has the following f.orm:

context inv



M. BADAWY AND K. RleHTA

308

where name is the constraint identification, and condition is an OCL expression over elements of T. The condition may include OCL functions, and it can include quantifiers, typically used to express general conditions over variables. From the logical point of view we can look at the OCL invariant specification as to the frrst-order logical formulae:

«name»

' e2.salary)

= e2.supervisor

The equivalent logic formula can be:

(C1) ' e1.salary > e2.salary Example 2. Suppose there is another integrity constraint C2 defining "Every department has at least one project managed by the department", in OCL:

context DEPT inv C2 : exist( p: PROJ I d.id

= p.managed_by)

Example 3. Finally, assume there is an integrity constraint C3 stating, "The total salary of the employees working in a department must not exceed the department's budget", in OCL:

context d:DEPT inv C3 : d.budget >= iterate(e:EMP sum = 0 I e.dept = d.id implies e.salary + sum )

309

DERIVING TRIGGERS FROM UML/OCL SPECIFICATION

5. DERIVING TRIGGERS FROM CONSTRAINT SPECIFICATIONS Before going into the details how triggers can be derived from constraint specifications, it is worth mentioning that this part assumes only integrity constraints that cannot be implemented using any declarative specifications. The SQL standard used in this pa~er is SQL: 199913. The reference DBMSes used are Oracle8i Server (Release 8.1.6), I IBM DB2 Universal Database (Version 7),18 Informix Dynamic Server (Version 9.1),19 Microsoft SQL Server (Version 7.0)/° Sybase Adaptive Server (Version 11.5)/1 and Ingress II (Release 2.0)22.

5.1. The Deriving Rules Given an integrity constraint C, the procedure to derive triggers has to determine the following: • • • •

Trigger event, Trigger granularity, Trigger condition, and Trigger activation time.

5.1.1. Determining a Trigger Event

The first task is to determine critical operations; that is, database modifications that can lead to a violation of C. Such operations are insert, update, and delete statements on tables. These operations eventually determine triggering events on base tables as part of any trigger specification. If one misses a critical operation, then the integrity constraint can be violated without the system reacting to the violation. By analogy, if an operation has been identified that actually can never violate the integrity constraint, implementing a respective trigger would be meaningless and only leads to a decrease in the system performance. So how can such critical operations be determined? Let us suppose the integrity constraint C I "The salary of a manager must be greater than the salary of an employee" expressed in OCL: ei.id

=

context EMP inv Ci : forA1l(ei,e2 e2.supervisor implies ei.salary > e2.salary)

Obviously, a deletion of an employee or manager from table EMP will not violate this integrity constraint. Only insertions into the table EMP and updates of the column salary can lead to a constraint violation. Updates on the column salary can even be refined further. Only salary increases for employees and salary decreases for managers can lead to a constraint violation. Suppose the integrity constraint C2 "Every department has at least one project managed by the department", in OCL: context DEPT inv C2 : exist( p: PROJ I d.id

= p.managed_by)

Again, for universally quantified variables, only insertions (and updates, here on the column id of table DEPT) on the associated table can lead to a constraint violation. In contrast, for tables covered by existentially quantified variables, deletions (and updates,

310

M. BADAWY AND K. RICHTA

here on the column managed_by of the table PROJ) from the associated table can lead to a constraint violation. But if the tables covered by negation of the existentially quantified variables, insertion (and updates, here on the column managed_by of the table PROJ) from the associated table can lead to a constraint violation. Finally, assume the integrity constraint C3 "The total salary of the employees working in a department must not exceed the department's budget", in OCL: context d:DEPT inv C3 : d.budget >= iterate(e:EMP sum = 0 I e.dept = d.id implies e.salary + sum )

Of course, decreasing a department's budget can violate this integrity constraint. Also, insertions into the table EMP and updates of the column salary of table EMP can lead to a violation of this integrity constraint. As a general rule for deriving critical operations from integrity constraint specifications we thus have: • • •

For tables that are covered by universally quantified variables (and by negation of the existentially quantified variables), insert operations are critical. For tables that are covered by existentially quantified variables, delete operations are critical. In both cases update operations on columns used in comparisons are critical.

Note that critical update operations can be refined further based on the type of comparison columns are involved in. Such refined updates prove to be useful for specifying triggering conditions. Critical operations are then based on the underlying base tables. Determining a critical set of operations for a set of integrity constraints eventually results in a set of (table, operation) pairs that specify critical operations on tables. 5.1.2. Determining Trigger Granularity

The second task is to determine for each such pair whether the check of the underlying integrity constraint can be performed for each individual row from the table affected by the operation, or only for all rows affected by that operation. In the former case, a row-level trigger should be used, and in the latter case a statement-level trigger. Again, some general rules can be given that are applicable to all reference systemss: •

• •

Almost all types of integrity constraint verifications based on (table, operation) pairs can be accommodated in statement-level triggers. For performance reasons, however, row-level triggers are preferable because they allow tailoring of verifying conditions to modified rows only. Integrity constraints that include aggregate functions always require at least one statement- level trigger, defined for the table and rows over which the aggregation is performed. In all reference systems, only row-level triggers allow a WHEN clause verifying properties of rows to be checked. This holds in particular for rows involved in the verification of state transition constraints. Typically, state transition constraints and their critical operations can only be verified using row-level triggers.

DERIVING TRIGGERS FROM UMUOCL SPECIFICATION

311

5.1.3. Determining a Trigger Condition

Once triggering events and trigger granularities have been determined, the next step in implementing constraint enforcing triggers is to formulate SQL statements that verify whether the integrity constraint from which a (table, operation) pair has been derived is violated. This is a crucial design task since one cannot use the original constraint but has to use its negation. That is, one has to specify a condition that checks whether there exists a row (or a combination of rows) for which the integrity constraint is violated. If such a row (or combination of rows) exists, the triggering action specifies how to react to the constraint violation, which is typically a rollback of the transaction. For instance, the violating condition for the integrity constraint Cl in Example 1, is formulated in SQL as follows: CHECK (NOT EXISTS (SELECT * (FROM EMP el, EMP e2 WHERE el.id = e2.supervisor AND el.salary e2.salary)

Secondly, we convert the OCL formulation into triggers (we use Oracle as a reference system) according to the deriving steps given above, as follows: 1.

By applying the general rules for deriving critical operations pairs, we have the following pairs: (EMP, insert) and (EMP, update (salary). 2. For the two critical operations above row-level triggers are sufficient but we also use in this case a statement-level trigger to overcome the mutating table problem. 3. In our reference system both BEFORE and AFTER are available. 4. It is not possible to define the triggering condition in trigger condition (WHEN clause) because it has a subquery, and subqueries are not allowed in the WHEN clause of the reference system. 5. The violating condition is inserting an employee with salary more than the manager's salary or updating the salary column so that the salary of any employee becomes more than the manager's salary. The violating condition has to be formulated in the trigger body.

DERIVING TRIGGERS FROM UML/OCL SPECIFICATION

313

From the above five steps, we can derive from the constraint specifications the triggers used to implement the above constraint C 1. In this case we will use three triggers: one row-level trigger and two statement-level triggers, as follows: •

The first trigger man_emp_sall is a BEFORE/STATEMENT trigger. It handles the temporary table, which we used to avoid the mutating/constraining table problem. We create a temporary table as follows: CREATE GLOBAL TEMPORARY TABLE TEMP_ EMP ( supervisor number (38) , number (38) , id salary number(7,2» ON COMMIT PRESERVE ROWS;

• •

The second trigger man_emp_saI2 is an AFTERIROW trigger. It is used to test the integrity violation and if so, it stores the old state of the table in the temporary table (TEMP_ EMP) to retrieve it later. The last one man_emp_saI3, which has an effect only when an integrity violation occurs, is an AFTERISTATEMENT trigger. It is used to retrieve the old state of the table from the temporary table to repair the violation. The three triggers are as follows:

CREATE OR REPLACE TRIGGER man_emp_sall BEFORE INSERT OR UPDATE OF salary ON EMP DECLARE 01 INTEGER; BEGIN SELECT COUNT(*) INTO C1 FROM TEMP_ EMP ; IF (01=0) THEN - initiate TEMP EMP INSERT INTO TEMP EMP SELECT supervisor,id,salary FROM EMP; END IF;

END; CREATE OR REPLACE TRIGGER man_emp_sal2 AFTER INSERT OR UPDATE OF salary ON EMP FOR EACH ROW DECLARE employeecnt INTEGER; managercnt INTEGER; BEGIN SELECT oount(*) INTO employeecnt FROM TEMP_EMP tmp WHERE tmp.id = supervisor AND salary >= :new.salary; SELECT oount(*) INTO managercnt FROM TEMP_EMP tmp WHERE tmp.supervisor = id AND salary 0) OR (managercnt > 0)) THEN IF UPDATING THEN UPDATE TEMP EMP SET TEMP_EMP.salary = :old.salary WHERE TEMP EMP.id :new.id; END IF; ELSE IF UPDATING THEN UPDATE TEMP EMP SET TEMP_EMP.salary = :new.salary WHERE TEMP EMP.id :new.id; END IF; IF INSERTING THEN INSERT INTO TEMP EMP VALUES (:new.id, :new.job, END IF; END IF; END;

:new.salary);

CREATE OR REPLACE TRIGGER man_emp_sa13 AFTER INSERT OR UPDATE OF salary ON EMP DECLARE c INTEGER; BEGIN IF INSERTING THEN DELETE FROM EMP WHERE id NOT IN (SELECT id FROM TEMP_EMP); END IF; IF UPDATING THEN SELECT COUNT (*) INTO C FROM EMP e, TEMP_EMP t WHERE e.id = t.id AND e.salary t.salary; IF(c>O) THEN UPDATE EMP SET salary = (SELECT salary FROM TEMP EMP WHERE TEMP EMP.id EMP.id); END IF; END IF; END;

DERIVING TRIGGERS FROM UMLlOCL SPECIFICATION

315

7. CONCLUSIONS In this paper we have provided some rules used to derive triggers from constraint specifications. By using these rules, deriving triggers becomes simpler. These rules are also general, so they can be used by any reference system. When using declarative integrity constraints there are many problems. SQL: 1999 defines an unlimited CHECK clause, but current implementations do not allow it. In our point of view, the best way is to convert the CHECK clause into triggers. We suggest that integrity constraints can be converted into a more formal description (e.g. OCL), decomposed, and then converted into triggers, as we have illustrated in this paper.

REFERENCES C. J. Date, An Introduction to Database Systems. Addison-Wesley Publishing Company, 6th edition, 1995. R. Cochrane, H. Pirahesh, and N. Mattos, Integrating Triggers and Declarative Constraints in SQL Database Systems. In Proc. of the 22'1