0

I'm struggling with a problem in Oracle 12.1 regarding to procedures.

We are using a data isolation approach based on schemas. We use one schema as PUBLIC and each project has exactly the same tables and procedures, but different data.

Problem: I need to get the schema name where the procedure was called in order to update a row for a table in the PUBLIC schema that holds all the different schemas.

Header definition

CREATE OR REPLACE PACKAGE PKG_DONE 
AUTHID DEFINER 
AS
  PROCEDURE ACK_FROM_WEB(UUID INTERNAL.UUID%TYPE, USERNAME PUBLIC.USERS.USER_NAME%TYPE);

END PKG_DONE;

Body definition

CREATE OR REPLACE PACKAGE BODY PKG_DONE AS
  PROCEDURE ACK_FROM_WEB(P_UUID INTERNAL.UUID%TYPE, P_USERNAME PUBLIC.USERS.USER_NAME%TYPE)
  AS
  BEGIN
    INSERT INTO ACK_WEB_USER(UUID,USERNAME) VALUES (P_UUID,P_USERNAME);
    UPDATE PUBLIC.ACK_CONFIRMATIONS SET ASSIGNED = P_USERNAME WHERE UUID = P_UUID AND SCHEMA_NAME = USER;
  END ACK_FROM_WEB;

END PKG_DONE;

It works perfectly in our website as we set the session with the SCHEMA when operating, but now we need external confirmation, via email and it only works with PUBLIC schema for security reasons. I would like to retrieve the schema where I call the procedure instead of USER in the statement UPDATE PUBLIC.ACK_CONFIRMATIONS SET ASSIGNED = P_USERNAME WHERE UUID = P_UUID AND SCHEMA_NAME = USER;.

Is there any command/dbms procedure or anything where I can get it?

1

You can use one of the functions of Oracles owa_util's package named WHO_CALLED_ME.

To demonstrate this feature, we can create a table which will store the results of the call to Oracle's procedure.

create table T_CALLSTACK (
    OWNER_NAME      varchar2(30),
    OBJECT_NAME     varchar2(30),
    LINE_NUMBER     number,
    CALLER_INFO     varchar2(100),
    INSERTDATE      date
);

As a test procedure which will insert some values we use:

create or replace procedure P_CALLED_BY_T is

    v_Owner          varchar2(30);
    v_PackageName    varchar2(30);
    v_LineNumber     number;
    v_CallerT        varchar2(100);

begin

    owa_util.WHO_CALLED_ME (v_Owner, v_PackageName, v_LineNumber, v_CallerT);

    -- v_Owner will contain the schema name of the procedure which
    -- called this procedure itself
    insert
      into T_CALLSTACK (OWNER_NAME, OBJECT_NAME, LINE_NUMBER, CALLER_INFO, INSERTDATE)
    values (v_Owner, v_PackageName, v_LineNumber, v_CallerT, sysdate);

end P_CALLED_BY_T;

The procedure WHO_CALLED_ME will return the schema's name as well as the package name and the line number inside the calling package body, caller-T is the type of database object which called our custom procedure P_CALLED_BY_T. If the caller itself is just a procedure, the variable v_PackageName will hold the procedure's name instead of a package name.

| improve this answer | |
  • Thanks for your feedback, as you can see I already found the solution that works for me. I'll try yours, looks clean. – user4951 Oct 15 '14 at 14:36
  • @jms yes, we literally answered the question at the same time. – mruether Oct 16 '14 at 9:06
1

Solution found.

After some research I got to a nice example on how to find the current user via dual. The solution is pretty simple just add select sys_context( 'userenv', 'current_user' ) into user_name from dual; and user user_name instead of user.

The body looks as follows

CREATE OR REPLACE PACKAGE BODY PKG_DONE AS
  PROCEDURE ACK_FROM_WEB(P_UUID INTERNAL.UUID%TYPE, P_USERNAME PUBLIC.USERS.USER_NAME%TYPE)
  AS
  user_name VARCHAR2(255 CHAR);
  BEGIN
    select sys_context( 'userenv', 'current_user' ) into user_name from dual;
    INSERT INTO ACK_WEB_USER(UUID,USERNAME) VALUES (P_UUID,P_USERNAME);
    UPDATE PUBLIC.ACK_CONFIRMATIONS SET ASSIGNED = P_USERNAME WHERE UUID = P_UUID AND SCHEMA_NAME = user_name;
  END ACK_FROM_WEB;

END PKG_DONE;

Long explanation:

Procedures can have AUTHID CURRENT_USER or AUTHID DEFINER (by default when no defined).

  • Using AUTHID CURRENT_USER gets the permissions from the schema that calls the procedure, hence the CURRENT_USER command was returning the schema whom was issuing the procedure, not the schema where it was stored.
  • Using AUTHID DEFINER (default if you specify nothing) doesn't get the permissions from the schema that calls the procedure, hence the CURRENT_USER command reports the schema that holds the procedure.
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy