Using SET_CONTEXT and SYS_CONTEXT - plsql

I have a PL/SQL package (say package1) which contains only 1 procedure. This procedure is used for security purpose and stores the application logged in user using SET_CONTEXT method.
I have another package (say package2) which contains several procedures related to application functionality but they use the SYS_CONTEXT to get the logged in user.
Whenever I want to call package2's procedures from Java, I want package1's procedure to be executed first and then package2's procedures. The reason is I want both these calls to happen in the same database connection.
Is there a way to configure this in Oracle instead of repeating the call to package1's procedure inside each and every package2's procedures.

Assuming your procedure in package1 is public (i.e., declared in the package specification), and assuming your package2 procedures have an EXECUTE authority on package1, one of the possible solutions will be using INITIALIZING PACKAGE .
The initialization consists of all the statements following the BEGIN statement at the end of the package declaration to the END statement
Ex.
PACKAGE BODY package2
IS
--All your package2 procedures
--initialization section at the end of package2:
BEGIN
package1.procedure1();
END package2;
This initialization section, will be run only the first time your session uses a package2 (by using any function/procedure in it). The package will be re-initialized in the same session if it is recompiled.

Another way to solve this problem is place code of package1 (package1.procedure1();) into user logon trigger or call that procedure from that trigger; please find example bellow for trigger
Example:
CREATE OR REPLACE TRIGGER hr_logon_trigger
AFTER LOGON
ON HR.SCHEMA
BEGIN
-- you code here or call to package1.procedure1();
END;

Related

sql developer stored procedure running without error

BEGIN
PROC_TEST('20-10-2020');
END;
I tried to execute this procedure,After executing output shows anonymous block completed. with out any error
but it is actually not compiled.
how solve this problem?
Compiled? You just executed an anonymous PL/SQL block which calls a procedure named PROC_TEST and passed a string as a parameter. I guess you meant to pass a DATE instead. Did you? If so, try
set serveroutput on
begin
proc_test(date '2020-10-20');
end;
/
instead.
Procedure executed successfully, regardless.
If you expected some kind of an output (via dbms_output.put_line, for example), enable serveroutput (like in my example, which works in SQL*Plus, SQL Developer or maybe some other tools as well; if not, enable it via GUI you use).
Finally, I don't see any problem here to be solved. What exactly do you have on mind?

Shared database and "An owner referenced by user does not have EXECUTE PROCEDURE access to" procedure

Is there a way around it in Teradata, if you have rights to create a procedure in the shared database, but fail to execute the first procedure inside the second procedure you created in the same database.
Attempted with SQL INVOKER and SQL CREATOR.
Tried an option to grant the execution explicitly, ended with the:
The user doesn't have CREATE PROCEDURE WITH GRANT OPTION access to database
What else can be done here?
.login server1/$user1,$pwd1
database shared_db;
replace proc proc1
SQL SECURITY CREATOR
begin
end;
replace proc proc2
begin
call proc1;
end;
-- errors
EDIT for Fred:
Database holding the procedures is shared (aka shared_db). User1 (who has the rights to create procedures in the shared_db) is creating proc1 in it, and proc2; the latter executes proc1 from its body.
EDIT 2 - concluded, setup needed was indeed (which is not that obvious)
GRANT EXECUTE ON shared_db.proc1 to shared_db;
The creator of PROC1 can
GRANT EXECUTE PROCEDURE ON shared_db.proc1 TO shared_db;

ORA-22285: non-existent directory or file for FILEOPEN operation

I am trying to insert code of XML file into a column which is of XMLtype
I have below query which is working fine
select extract(xmlcol,'/*')
from (SELECT xmltype(BFILENAME('MEDIA_DIR', 'xmldata1.xml'),nls_charset_id('UTF-8')) xmlcol FROM dual)
On running this query I am getting the Xmlcode inside the xml file(xmldata1) in one row.
Now, As per my requirement I have created a type which reads data from the XMLfile.
Below is the code of member function of the type:
create or replace type body t_emp
as
member function get_xml return xmltype is
v_xml xmltype;
begin
select extract(xmlcol,'/*') into v_xml
from (SELECT xmltype(BFILENAME('MEDIA_DIR', 'xmldata1.xml'),nls_charset_id('UTF-8')) xmlcol FROM dual);
return v_xml;
end get_xml;
end;
I am calling this type member function in my code. Below is the code
declare
t_emp1 t_emp;
r1 xmltype;
begin
t_emp1 := t_emp(2);
r1 := t_emp1.get_xml;
insert into EMPLOYEE_XML values (t_emp1.id,r1);
end;
Here variable r1 is of importance as I am fetching XML data in this variable.
On running this code I am getting below error:
ORA-22285: non-existent directory or file for FILEOPEN operation
I am not able to understand why this error is coming as the directory exist. I am able to run previously mentioned SQL query.
Thanks!!
The user you are creating the type as only has permissions on the directory object granted through a role. Privileges from roles are not inherited by stored PL/SQL blocks by default. When you run the SQL directly the role is enabled; when you run in through the PL/SQL member function the role is disabled and the directory is not visible to your user. You need the directory privileges to be granted directly to your user.
In your case you are working in the SYSTEM schema (so the directory privilege is coming via the EXP_FULL_DATABASE role, which comes from DBA), which is a bad idea; it is not good practice to create objects in that schema (or any built-in schema), so granting privileges directly to `SYSTEM would also be a mistake here.
You should create a new user/schema, with the minimum privileges it needs. You've already created the directory object, so the new user set-up would include:
grant read,write on media_dir to your_new_user;
You can then create the type and its member function in that new schema, and you'll be able to execute it from your anonymous block.
If you can only have privileges granted through a role then you could instead change the type declaration to use invoker's rights
create or replace type t_emp authid current_user as object ...
That would even work in your current scenario, sticking with SYSTEM; but again you really shouldn't be working in that schema.

Using Logs in stored Procedure

I need help in creating logs in a stored procedure.
Scenario is like:
I am creating a procedure. I need to log some intermediate information from the procedure in a log file, such that each time the procedure is executed the logs are generated.
Normally i was using SPOOL for this purpose, but as SPOOL is SQL PLUS and cannot be used in PL/SQL, i was look for a better way through which logs written to specific file each time the procedure is triggered informing the updates which are made in the procedure.
Can someone please help me in identifying any such code snap which i can insert in the stored procedure in order to meet my requirement.
NOTE: I am using Oracle.
You could simply create a package with simple logging functionality, which opens, writes and closes a log file that is stored on the database server. Look into the UTL_FILE package;

Reference different schema using "alter session set current_schema" inside a package

Is it possible to do
alter session set current_schema=MySchema;
inside a package?
Our asp.net web application call Oracle packages. We'd like to connect to database with an Oracle user that is not the owner of MySchema. For that, we grant execute permissions on Other_User to package MyPackage.
Example:
grant execute on MySchema.MyPackage to Other_User
But when web app connects to Oracle and try to execute the stored procedures of MyPackage, it gets errors because tables don't belong to Other_User.
One way to avoid errors is creating synonyms, but we would prefere to use
alter session set current_schema=MySchema;
if possible, inside the package.
EDIT: When trying to put "alter session" in package:
You cannot use DDL statements (which ALTER SESSION is) directly in PL/SQL.
You need to use an EXECUTE IMMEDIATE:
execute immediate 'alter session set current_schema=MySchema';

Resources