Wednesday, 2 June 2021

PRAGMA RESTRICT_REFERENCES

 

PRAGMA RESTRICT_REFERENCES:

PRAGMA RESTRICT_REFERENCES uses to control the side effects of PL/SQL Subprograms. Every PL/SQL Subprograms must follow some rules in terms of transaction control and security. 

The RESTRICT REFERENCES Pragma asserts that a user-defined subprogram does not read or write database tables or package variables.

syntax:

PRAGMA RESTRICT_REFERENCES ( [SUBPROGRAM_NAME/DEFAULT] , [RNDS, WNDS, RNPS, WNPS, TRUST]);

DEFAULT

Specifies that the pragma applies to all subprograms in the package specification or object type specification (including the system-defined constructor for object types).

You can still declare the pragma for individual subprograms, overriding the DEFAULT pragma.

RNDS

Asserts that the subprogram reads no database state (does not query database tables).

WNDS

Asserts that the subprogram writes no database state (does not modify tables).

RNPS

Asserts that the subprogram reads no package state (does not reference the values of packaged variables)

You cannot specify RNPS if the subprogram invokes the SQLCODE or SQLERRM function.

WNPS

Asserts that the subprogram writes no package state (does not change the values of packaged variables).

You cannot specify WNPS if the subprogram invokes the SQLCODE or SQLERRM function.

TRUST

Asserts that the subprogram can be trusted not to violate one or more rules.

When you specify TRUST, the subprogram body is not checked for violations of the constraints listed in the pragma. The subprogram is trusted not to violate them. Skipping these checks can improve performance. TRUST is needed for functions written in C or Java that are invoked from PL/SQL, since PL/SQL cannot verify them at run time.

About It:

  • The name of a user-defined subprogram, usually a function.
  • If subprogram_name is overloaded, the pragma applies only to the most recent subprogram declaration.
  • A RESTRICT_REFERENCES pragma can appear only in a package specification or object type specification. Typically, this pragma is specified for functions. If a function calls procedures, specify the pragma for those procedures also.
  • To invoke a subprogram from parallel queries, you must specify all four constraints—RNDS, WNDS, RNPS, and WNPS. No constraint implies another.
  • However, by definition, autonomous routines never violate the rules read no database state (RNDS) and write no database state (WNDS) no matter what they do. This can be useful

 

Example: declaring restrict reference with autonomous transaction:

When you invoke the packaged function log_msg from a query, it inserts a message into database table debug_output without violating the rule write no database state.

— create the debug table
CREATE TABLE debug_output (msg VARCHAR2(200));

— create the package spec
CREATE PACKAGE debugging AS
   FUNCTION log_msg (msg VARCHAR2) RETURN VARCHAR2;
   PRAGMA RESTRICT_REFERENCES(log_msg, WNDS, RNDS);
END debugging;
/
— create the package body
CREATE PACKAGE BODY debugging AS
   FUNCTION log_msg (msg VARCHAR2) RETURN VARCHAR2 IS
   PRAGMA AUTONOMOUS_TRANSACTION;
   BEGIN
      — the following insert does not violate the constraint
      — WNDS because this is an autonomous routine
      INSERT INTO debug_output VALUES (msg);
      COMMIT;
      RETURN msg;
   END;
END debugging;
/
— invoke the packaged function from a query
DECLARE
   my_emp_id    NUMBER(6);
   my_last_name VARCHAR2(25);
   my_count     NUMBER;
BEGIN
   my_emp_id := 120;
   SELECT debugging.log_msg(last_name)
   INTO my_last_name FROM employees
   WHERE employee_id = my_emp_id;
— even if you roll back in this scope, the insert into ‘debug_output’ remains
— committed because it is part of an autonomous transaction
   ROLLBACK;
END;
/

example for different state:

RNDS:

CREATE OR REPLACE PACKAGE debugging AS
   FUNCTION log_msg (msg VARCHAR2) RETURN VARCHAR2;
   PRAGMA RESTRICT_REFERENCES(log_msg, RNDS); — (read no database state)
END debugging;
/

CREATE OR REPLACE PACKAGE BODY debugging AS
str VARCHAR2(10);
   FUNCTION log_msg (msg VARCHAR2) RETURN VARCHAR2 IS

   BEGIN
      SELECT msg INTO debugging.str FROM debug_output WHERE msg=’chinu’; –this statement will cause error
      INSERT INTO debug_output VALUES (msg);
      COMMIT;
      RETURN msg;
   END;

WNDS:

CREATE OR REPLACE PACKAGE debugging AS
   FUNCTION log_msg (msg VARCHAR2) RETURN VARCHAR2;
   PRAGMA RESTRICT_REFERENCES(log_msg, WNDS); — (read no database state)
END debugging;
/

CREATE OR REPLACE PACKAGE BODY debugging AS
str VARCHAR2(10);
   FUNCTION log_msg (msg VARCHAR2) RETURN VARCHAR2 IS

   BEGIN
      SELECT msg INTO debugging.str FROM debug_output WHERE msg=’chinu’;
      INSERT INTO debug_output VALUES (msg); –this statement will cause error
      COMMIT;
      RETURN msg;
   END;

RNPS:

 CREATE OR REPLACE PACKAGE debugging AS
   FUNCTION log_msg (msg VARCHAR2) RETURN VARCHAR2;
   PRAGMA RESTRICT_REFERENCES(log_msg, RNPS);
END debugging;
/

CREATE OR REPLACE PACKAGE BODY debugging AS
str VARCHAR2(10);
   FUNCTION log_msg (msg VARCHAR2) RETURN VARCHAR2 IS

   BEGIN
      IF str=’hi’ THEN       –this statement will cause error
        dbms_output.put_line(str); END IF;     
      SELECT msg INTO debugging.str FROM debug_output WHERE msg=’chinu’;
      INSERT INTO debug_output VALUES (msg);
      COMMIT;
      RETURN msg;
   END;
END debugging;
/

WNPS:

CREATE OR REPLACE PACKAGE debugging AS
   FUNCTION log_msg (msg VARCHAR2) RETURN VARCHAR2;
   PRAGMA RESTRICT_REFERENCES(log_msg, WNPS);
END debugging;
/

CREATE OR REPLACE PACKAGE BODY debugging AS
str VARCHAR2(10);
   FUNCTION log_msg (msg VARCHAR2) RETURN VARCHAR2 IS

   BEGIN
      IF str=’hi’ THEN
        dbms_output.put_line(str); END IF;     
      SELECT msg INTO debugging.str FROM debug_output WHERE msg=’chinu’; –this statement will cause error
      INSERT INTO debug_output VALUES (msg);
      COMMIT;
      RETURN msg;
   END;
END debugging;
/

TRUST: This state is something, which is not checking the subprogram body whether it is violating the constraint imposed by pragma or not. generally it is used when a function (written in C or java) is calling from the PL/SQL code.

Example: (Try the below program which imposed “TRUST” pragma state.)

CREATE OR REPLACE PACKAGE BODY debugging AS
   str VARCHAR2(10);
   FUNCTION log_msg (msg VARCHAR2) RETURN VARCHAR2 IS

   BEGIN
      IF str=’hi’ THEN
      dbms_output.put_line(str);  END IF;     
      SELECT msg INTO debugging.str FROM debug_output WHERE msg=’chinu’;
      INSERT INTO debug_output VALUES (msg);
      COMMIT;
      RETURN msg;
   END;
END debugging;
/

 for other pragma states except “TRUST” will throw error in above subprogram.

 

No comments: