Tuesday, July 24, 2012

UTL_FILE.FGETATTR returns ORA-1426 for files larger than 2GB (Versions < 10.2)

PROBLEM:
If file size is larger than 2GB, utl_file.fgetattr returns ORA-1426.
If file size is less than 2GB, correct result returns.

NOTE:
When using UTL_FILE.FGETATTR to get the size of a file which is greater than what a BINARY_INTEGER can handle, and fails with Numeric Overflow, you are seeing this bug. Versions confirmed as being affected: 9.2.0.4, 10.1.0.2. This issue is fixed in 9.2.0.6 (Server Patch Set), 10.1.0.3 (Server Patch Set), 10.2.0.1 (Base Release).
set serveroutput on
declare
   file_exists boolean := false;
   file_length number;
   block_size  number;
begin
 
   utl_file.fgetattr(
      location    => 'DATA_PUMP_DIR',
      filename    => 'my_big_dump_file.dmp',
      fexists     => file_exists,
      file_length => file_length,
      block_size  => block_size);
      
   if (file_exists) then
      dbms_output.put_line('file_exist = true');
   else
      dbms_output.put_line('file_exist = true');
   end if;
   
   dbms_output.put_line('file_length = ' || file_length);
   dbms_output.put_line('block_size  = ' || block_size);
   
end;
/

declare
*
ERROR at line 1:
ORA-1426: numeric overflow
ORA-6512: at "SYS.UTL_FILE", line 18
ORA-6512: at "SYS.UTL_FILE", line 1081
ORA-6512: at line 6
WORKAROUND #1
set serveroutput on
declare
   v_file_handle utl_file.file_type;
   ex_inv_file_op exception; pragma exception_init(ex_inv_file_op, -29283);
begin
 
   v_file_handle := utl_file.fopen(
      location  => 'DATA_PUMP_DIR',
      filename  => 'my_big_dump_file.dmp',
      open_mode => 'R');

   if utl_file.is_open(v_file_handle) then
      dbms_output.put_line('file_exist = TRUE');    
   end if;      

exception 
   when ex_inv_file_op then 
      dbms_output.put_line('file_exist = FALSE');
   
end;
/
file_exist = TRUE
WORKAROUND #2
set serveroutput on
declare
   v_file_handle bfile := null;
   v_file_exists boolean := false;
begin
 
   v_file_handle := bfilename(
      directory => 'DATA_PUMP_DIR',
      filename  => 'my_big_dump_file.dmp');
      
   v_file_exists := dbms_lob.fileexists(v_file_handle) = 1;

   if v_file_exists then
      dbms_output.put_line('file_exist = TRUE');    
   else
      dbms_output.put_line('file_exist = FALSE');
   end if;   
   
end;
/
file_exist = TRUE
Metalink: Bug 3354447 - UTL_FILE.FGETATTR returns ORA-1426 for files larger than 2Gb [ID 3354447.8]

No comments:

Post a Comment