Advanced Oracle PL/SQL Programming with Packages

Advanced Oracle PL/SQL Programming with PackagesSearch this book
Previous: 20.1 PLVcmt: Enhancing Commit ProcessingChapter 20
PLVcmt and PLVrb: Commit and Rollback Processing
Next: 21. PLVlog and PLVtrc: Logging and Tracing
 

20.2 PLVrb: Performing Rollbacks

The PLVrb PL/Vision RollBack package provides a programmatic interface to rollback activity in PL/SQL. With PLVrb, you no longer issue explicit ROLLBACK and SAVEPOINT commands. Instead, you call the appropriate PLVrb module. This layer of code gives you the ability to change transaction-level behavior at runtime. With PLVrb, you can even execute soft-coded savepoints, a feat usually considered impossible in PL/SQL.

These different elements of the PLVrb package are explained in the following sections.

20.2.1 Controlling Rollbacks

One of the big advantages to using PLVrb instead of direct calls to ROLLBACK is that you have placed a layer of code between your application and the ROLLBACK. This layer gives you (through PL/Vision) the ability to modify rollback processing behavior without changing your application code. This is very important because it allows you to stabilize your code, but still change the way it works for purposes of testing and debugging.

PLVrb offers a standard PL/Vision toggle to control rollback processing. This triumvirate of programs is:

PROCEDURE turn_on;
PROCEDURE turn_off;
FUNCTION rolling_back RETURN BOOLEAN;

All that the first two procedures do is set the value of a private Boolean variable, but by correctly applying that Boolean inside an IF statement in PLVrb, the package's user gets to fine-tune the package's behavior.

20.2.2 Logging Rollbacks

The rollback action in an application is a critical step. It is, for one thing, irreversible. Once you rollback, you cannot un-rollback. It is often very useful to know when rollbacks have taken place and the action that was taken around that rollback point. I have found this to be most important when I am executing long-running processes. Have I issued any rollbacks? If so, what was the cause? The PLVrb logging facility gives me the answers to these types of questions.

Whenever you call PLVrb.perform_rollback, PLVrb.rb_to_last, and PLVrb.rollback_to, you can supply a string or context for that action. This string is ignored unless logging is turned on. If logging is enabled, PLVrb calls the PLVlog facility to log your message. You can, within PLVlog, send this information to a database table, PL/SQL table, operating system file (with Release 2.3 of PL/SQL), or standard output (your screen).

PLVrb offers a standard PL/Vision toggle to control the logging of rollback processing. This triumvirate of programs is:

PROCEDURE log;
PROCEDURE nolog;
FUNCTION logging RETURN BOOLEAN;

NOTE: You do not have to turn on logging in PLVlog for the PLVrb log to function properly. It automatically turns on logging in PLVlog in order to write its rollback-related information, and then reset the PLVlog status to its prior state.

20.2.3 Setting Savepoints

When you set a savepoint in PL/SQL, you give yourself a spot in your code to which you can rollback your changes. This is useful when you need to discard some, but not all, of your uncommitted changes. The usual situation you face with PL/SQL is that you must hard code the names of savepoints in your code. A savepoint is, in fact, an undeclared identifier. You don't (and cannot) declare a savepoint in your declaration section, as you would with an exception. Instead, you simply provide an identifier after the keyword SAVEPOINT in your code and that savepoint is established. Then, when you issue a ROLLBACK, you must also hard code that same identifier value in the ROLLBACK.

In the following block of code, I set a savepoint and then in the exception section rollback to that same savepoint.

BEGIN
   SAVEPOINT start_trans;
   INSERT INTO emp ...;
   DELETE FROM emp_history ... ;
EXCEPTION
   WHEN OTHERS
   THEN
      ROLLBACK TO start_trans;
END;

I cannot, on the other hand, write code like this:

PACKAGE empsav
IS
   insert_point VARCHAR2(10) := insert ;
   delete_point VARCHAR2(10) := delete ;
END;

BEGIN
   SAVEPOINT empsav.insert_point;
   INSERT INTO emp ... ;
   SAVEPOINT empsav.delete_point;
   DELETE FROM emp_history ... ;
EXCEPTION
   WHEN DUP_VAL_ON_INDEX
   THEN
      ROLLBACK TO empsav.insert_point;

   WHEN empsav.still_active
   THEN
      ROLLBACK TO empsav.delete_point;
END;

PL/SQL will not, absolutely not, evaluate the packaged contents into a literal and then use that literal to direct rollback activity. Instead, the code will fail to compile as shown:

SAVEPOINT empsav.insert_point;
                *
ERROR at line 2:
ORA-06550: line 2, column 20:
PLS-00103: Encountered the symbol "." when expecting one of the
   following:

One consequence of this hard-coding is that you must know the name of the savepoint at compile time, not at runtime. In most situations, this might be fine. In other programs, this can be a significant obstacle. PLVlog, for example, offers a generic logging mechanism. When logging to a database table, you must often perform a ROLLBACK before an INSERT to the log table and then follow up with the setting of a SAVEPOINT. And it really needs to do these steps for a dynamically determined savepoint.

This dynamic setting of savepoints (and rolling back to those savepoints) is provided by the PLVrb package. To set a savepoint whose name is determined at runtime, call the set_savepoint procedure. The header for this program is:

   PROCEDURE set_savepoint (sp_in IN VARCHAR2);

where sp_in is the savepoint name. The sp_in argument must be a valid PL/SQL identifier (starts with a letter, is composed of letters, digits, $, #, and the underscore character, and must be no longer than 30 characters in length).

Every time you set a savepoint, the procedure takes the following actions:

  1. Set the savepoint with a call to PLVdyn.plsql. The set_savepoint programs constructs the SAVEPOINT command and executes it dynamically.

  2. Sets the last savepoint value to the provided savepoint.

  3. Pushes the savepoint onto the stack of savepoints maintained by PLVrb using the PLVstk package.

Instead of issuing statements like this:

SAVEPOINT start_trans;

you can now pass the name of your savepoint to PLVrb for setting:

PLVrb.set_savepoint ('start_trans');

or:

PLVrb.set_savepoint (v_starttrans_sp);

20.2.4 Performing Rollbacks

PLVrb offers three programs to perform rollbacks: perform_rollback, rollback_to, and rb_to_last. The headers for these programs are:

PROCEDURE perform_rollback
   (context_in IN VARCHAR2 := NULL);

PROCEDURE rollback_to
   (sp_in IN VARCHAR2,
    context_in IN VARCHAR2 := NULL);

PROCEDURE rb_to_last
   (context_in IN VARCHAR2 := NULL);

In all three procedures, the context_in argument is a string that will be logged using PLVlog if you have called PLVrb.log to turn on logging.

When you call perform_rollback, a full, unqualified rollback is performed; no savepoint is used, and all uncommitted changes are rolled back.

When you call rollback_to, PLVrb issues a ROLLBACK to the specified savepoint. Besides issuing the savepoint, PLVrb also removes from the savepoint stack any savepoints that came after the savepoint you specified. If the savepoint argument is not in the PLVrb savepoint stack, the stack is emptied.

When you call rb_to_lst, PLVrb issues a ROLLBACK to the savepoint specified in the most recent call to set_savepoint.


Previous: 20.1 PLVcmt: Enhancing Commit ProcessingAdvanced Oracle PL/SQL Programming with PackagesNext: 21. PLVlog and PLVtrc: Logging and Tracing
20.1 PLVcmt: Enhancing Commit ProcessingBook Index21. PLVlog and PLVtrc: Logging and Tracing

The Oracle Library Navigation

Copyright (c) 2000 O'Reilly & Associates. All rights reserved.

Library Home Oracle PL/SQL Programming, 2nd. Ed. Guide to Oracle 8i Features Oracle Built-in Packages Advanced PL/SQL Programming with Packages Oracle Web Applications Oracle PL/SQL Language Pocket Reference Oracle PL/SQL Built-ins Pocket Reference