plsqloracle11gxmltype

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!!


Solution

  • 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 directory 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.