Reputation: 41
Could you tell me, why this function returns as result an empty blob value? It don't even close the BFILE type variable after the loop. I can't imaging where is the problem.
FUNCTION f$bfile_to_blob
(I_FID_ID IN INTEGER)
RETURN BLOB IS
bf BFILE;
Amount INTEGER := 32767;
Position integer := 1;
buffer RAW(32767);
bl LONG RAW := '';
bb BLOB;
BEGIN
select fid_bckp into bf
from filedoc
where fid_id = I_FID_ID;
dbms_lob.open(bf, dbms_lob.lob_readonly);
DBMS_LOB.CREATETEMPORARY(bb, TRUE, DBMS_LOB.SESSION);
LOOP
dbms_lob.read(bf, Amount, Position, buffer);
dbms_lob.writeappend(bb,amount,buffer);
Position := Position + Amount;
END LOOP;
dbms_lob.close(bf);
return bb;
END;
I call the function this way
select F$BFILE_TO_BLOB(fid_id) from filedoc where fid_id = 2150;
Upvotes: 3
Views: 4654
Reputation: 67722
Your logic is complex, you're mixing many elements that can produce errors: namely CLOB and BFILE. You should try first to isolate which element in your function leads to this abnormal behaviour.
I suggest you run a simple function to make sure that your BLOB logic is fine:
create or replace FUNCTION f$bfile_to_blob
RETURN BLOB IS
bb BLOB;
BEGIN
DBMS_LOB.CREATETEMPORARY(bb, TRUE, DBMS_LOB.SESSION);
bb := hextoraw('FFFFFFFF');
return bb;
END;
select rawtohex(dbms_lob.substr(f$bfile_to_blob, 4000, 1)) from dual;
This should produce FFFFFFFF. Now you know that the problem lies with your reading of the BFILE object. We can see in your code that you have a loop withoug an exit condition. Since the program exits, we deduct that your loop exits with an error.
The documentation explains that the exception is raised by the READ
procedure:
The number of bytes or characters actually read is returned in the amount parameter. If the input offset points past the End of LOB, then amount is set to 0, and a NO_DATA_FOUND exception is raised.
The exception is raised and the function exits without having return anything.
As you may know, NO_DATA_FOUND
exceptions are not considered errors inside an SQL statement. The error is interpreted as NULL
by the SELECT
query.
You should modify your function to catch this error and exit the loop gracefully:
FUNCTION f$bfile_to_blob(I_FID_ID IN INTEGER)
RETURN BLOB IS
bf BFILE;
Amount INTEGER := 32767;
Position INTEGER := 1;
buffer RAW(32767);
bl LONG RAW := '';
bb BLOB;
BEGIN
SELECT fid_bckp
INTO bf
FROM filedoc
WHERE fid_id = I_FID_ID;
dbms_lob.open(bf, dbms_lob.lob_readonly);
DBMS_LOB.CREATETEMPORARY(bb, TRUE, DBMS_LOB.SESSION);
LOOP
BEGIN
dbms_lob.read(bf, Amount, Position, buffer);
EXCEPTION
WHEN NO_DATA_FOUND THEN
EXIT;
END;
dbms_lob.writeappend(bb, amount, buffer);
Position := Position + Amount;
END LOOP;
dbms_lob.close(bf);
RETURN bb;
END;
Upvotes: 1