Assertion Package Specification
CREATE OR REPLACE PACKAGE assert
/*
Assertion Package
Provides a set of procedures you can use to *assert*
that a required condition is met. If not, an
error is raised, stopping execution of the block.
Author: Steven Feuerstein, steven.feuerstein@oracle.com
Example:
instead of this:
PROCEDURE calc_totals (
dept_in IN INTEGER,
date_in IN DATE
)
IS
bad_date EXCEPTION;
BEGIN
IF dept_in IS NULL
THEN
RAISE_APPLICATION_ERROR (-20000, 'Department ID cannot be null.');
END IF;
IF date_in NOT BETWEEN ADD_MONTHS (SYSDATE, -60) AND SYSDATE
THEN
RAISE_APPLICATION_ERROR (-20000, 'Date is out of range.');
END IF;
-- Program logic
END;
Do this:
PROCEDURE calc_totals (
dept_in IN INTEGER,
date_in IN DATE
)
IS
bad_date EXCEPTION;
PROCEDURE validate_assumptions
IS
BEGIN
assert.is_null (dept_in, 'Department ID');
assert.is_in_range (
date_in,
ADD_MONTHS (SYSDATE, -60),
SYSDATE
);
END;
BEGIN
validate_assumptions;
-- Everything's fine. Code in confidence...
-- Program logic
END;
*/
IS
PROCEDURE this_condition (
condition_in IN BOOLEAN
, msg_in IN VARCHAR2
, display_call_stack_in IN BOOLEAN DEFAULT FALSE
, null_means_failure_in IN BOOLEAN DEFAULT TRUE
);
PROCEDURE is_null (
val_in IN VARCHAR2
, msg_in IN VARCHAR2
, display_call_stack_in IN BOOLEAN DEFAULT FALSE
);
PROCEDURE is_not_null (
val_in IN VARCHAR2
, msg_in IN VARCHAR2
, display_call_stack_in IN BOOLEAN DEFAULT FALSE
);
PROCEDURE is_true (
condition_in IN BOOLEAN
, msg_in IN VARCHAR2
, display_call_stack_in IN BOOLEAN DEFAULT FALSE
);
PROCEDURE is_false (
condition_in IN BOOLEAN
, msg_in IN VARCHAR2
, display_call_stack_in IN BOOLEAN DEFAULT FALSE
);
PROCEDURE is_in_range (
date_in IN DATE
, low_date_in IN DATE
, high_date_in IN DATE
, msg_in IN VARCHAR2
, display_call_stack_in IN BOOLEAN DEFAULT FALSE
);
END assert;
Package created.
Assertion Package Body
CREATE OR REPLACE PACKAGE BODY assert
IS
PROCEDURE this_condition (
condition_in IN BOOLEAN
, msg_in IN VARCHAR2
, display_call_stack_in IN BOOLEAN DEFAULT FALSE
, null_means_failure_in IN BOOLEAN DEFAULT TRUE
)
IS
BEGIN
IF NOT condition_in
OR (null_means_failure_in AND condition_in IS NULL)
THEN
IF display_call_stack_in
THEN
DBMS_OUTPUT.put_line ('ASSERTION VIOLATION! ' || msg_in);
DBMS_OUTPUT.put_line ('Path taken to assertion violation:');
/* Uncomment when you install in your own environment;
DBMS_UTILITY currently unavailable in LiveSQL
DBMS_OUTPUT.put_line (DBMS_UTILITY.format_call_stack); */
END IF;
raise_application_error (-20000, 'ASSERTION VIOLATION! ' || msg_in);
END IF;
END;
PROCEDURE is_null (
val_in IN VARCHAR2
, msg_in IN VARCHAR2
, display_call_stack_in IN BOOLEAN DEFAULT FALSE
)
IS
BEGIN
this_condition (val_in IS NULL
, msg_in
, display_call_stack_in
, null_means_failure_in => FALSE
);
END is_null;
PROCEDURE is_not_null (
val_in IN VARCHAR2
, msg_in IN VARCHAR2
, display_call_stack_in IN BOOLEAN DEFAULT FALSE
)
IS
BEGIN
this_condition (val_in IS NOT NULL, msg_in, display_call_stack_in);
END is_not_null;
PROCEDURE is_true (
condition_in IN BOOLEAN
, msg_in IN VARCHAR2
, display_call_stack_in IN BOOLEAN DEFAULT FALSE
)
IS
BEGIN
this_condition (condition_in, msg_in, display_call_stack_in);
END is_true;
PROCEDURE is_false (
condition_in IN BOOLEAN
, msg_in IN VARCHAR2
, display_call_stack_in IN BOOLEAN DEFAULT FALSE
)
IS
BEGIN
this_condition (NOT condition_in, msg_in, display_call_stack_in);
END is_false;
PROCEDURE is_in_range (
date_in IN DATE
, low_date_in IN DATE
, high_date_in IN DATE
, msg_in IN VARCHAR2
, display_call_stack_in IN BOOLEAN DEFAULT FALSE
)
IS
BEGIN
this_condition (TRUNC (date_in) BETWEEN TRUNC (low_date_in)
AND TRUNC (high_date_in)
, msg_in
, display_call_stack_in
);
END is_in_range;
END assert;
Package Body created.
Create Example Procedure
CREATE OR REPLACE PROCEDURE calc_totals (
dept_in IN INTEGER,
date_in IN DATE
)
IS
PROCEDURE validate_assumptions
IS
BEGIN
assert.is_not_null (dept_in, 'Department ID cannot be NULL');
assert.is_in_range (
date_in,
ADD_MONTHS (SYSDATE, -60),
SYSDATE,
'date_in is out of range'
);
END;
BEGIN
validate_assumptions;
DBMS_OUTPUT.PUT_LINE ('No violations of assumptions!');
END;
Procedure created.
Exercise the Assertion Package
BEGIN
calc_totals (NULL, SYSDATE - 1);
END;
ORA-20000: ASSERTION VIOLATION! Department ID cannot be NULL ORA-06512: at "SQL_RHMNFZMBVXMXUDWPPFNBLLUVE.ASSERT", line 24 ORA-06512: at "SQL_RHMNFZMBVXMXUDWPPFNBLLUVE.ASSERT", line 49 ORA-06512: at "SQL_RHMNFZMBVXMXUDWPPFNBLLUVE.CALC_TOTALS", line 9 ORA-06512: at "SQL_RHMNFZMBVXMXUDWPPFNBLLUVE.CALC_TOTALS", line 19 ORA-06512: at line 2 ORA-06512: at "SYS.DBMS_SQL", line 1721More Details: https://docs.oracle.com/error-help/db/ora-20000
Exercise the Assertion Package
BEGIN
calc_totals (1, SYSDATE + 1);
END;
ORA-20000: ASSERTION VIOLATION! date_in is out of range ORA-06512: at "SQL_RHMNFZMBVXMXUDWPPFNBLLUVE.ASSERT", line 24 ORA-06512: at "SQL_RHMNFZMBVXMXUDWPPFNBLLUVE.ASSERT", line 81 ORA-06512: at "SQL_RHMNFZMBVXMXUDWPPFNBLLUVE.CALC_TOTALS", line 11 ORA-06512: at "SQL_RHMNFZMBVXMXUDWPPFNBLLUVE.CALC_TOTALS", line 19 ORA-06512: at line 2 ORA-06512: at "SYS.DBMS_SQL", line 1721More Details: https://docs.oracle.com/error-help/db/ora-20000
Exercise the Assertion Package
BEGIN
calc_totals (1, SYSDATE - 1);
END;
No violations of assumptions!