SaveBlobToFile (WIP)
This commit is contained in:
parent
8aac65cc81
commit
1ad24d3f71
@ -70,6 +70,14 @@
|
||||
|
||||
#include <limits>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#define SYSERROR() GetLastError()
|
||||
#else
|
||||
#include <errno.h>
|
||||
#define SYSERROR() errno
|
||||
#endif
|
||||
|
||||
using namespace Firebird;
|
||||
|
||||
|
||||
@ -243,8 +251,7 @@ FB_UDR_EXECUTE_FUNCTION
|
||||
throw Firebird::FbException(status, statusVector);
|
||||
}
|
||||
catch (...) {
|
||||
// This generates an unrecognised C++ exception, which is insufficient.
|
||||
throw std::runtime_error("Error writing stream to BLOB.");
|
||||
throw std::runtime_error("Error writing file to BLOB.");
|
||||
}
|
||||
|
||||
}
|
||||
@ -267,7 +274,7 @@ engine udr;
|
||||
FB_UDR_BEGIN_FUNCTION(MFK_SaveBlobToFile)
|
||||
//BEGIN
|
||||
FB_UDR_MESSAGE(InMessage,
|
||||
(FB_CHAR(8191), afilename)
|
||||
(FB_VARCHAR(8191), afilename)
|
||||
(FB_BLOB, ablob)
|
||||
);
|
||||
|
||||
@ -277,7 +284,8 @@ FB_UDR_MESSAGE(OutMessage,
|
||||
|
||||
AutoRelease<IAttachment> att;
|
||||
AutoRelease<ITransaction> tra;
|
||||
AutoRelease<IBlob> Blob;
|
||||
AutoRelease<IBlob> blob;
|
||||
ISC_STATUS_ARRAY statusVector = {0};
|
||||
|
||||
|
||||
FB_UDR_EXECUTE_FUNCTION
|
||||
@ -292,47 +300,68 @@ FB_UDR_EXECUTE_FUNCTION
|
||||
* DOC NOTE - We do not test for existence of the file here!
|
||||
*/
|
||||
|
||||
std::fstream File ( in->afilename.str , std::fstream::out | std::fstream::binary | std::fstream::app );
|
||||
if (! File.is_open()) {
|
||||
out->result = -2;
|
||||
std::ofstream FileWriter ( in->afilename.str , std::ofstream::binary );
|
||||
if (! FileWriter.is_open()) {
|
||||
out->resultNull = FB_TRUE;
|
||||
// Convert system error to a negative value and assign to result
|
||||
out->result = ( SYSERROR() * -1 );
|
||||
// important to set this to false here otherwise the error code will
|
||||
// be hidden and NULL returned to the firebird engine. This is because
|
||||
// the test for out->resultNull has precedence.
|
||||
if ( out->result < 0 ) {
|
||||
out->resultNull = FB_FALSE;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Blob.reset(att->openBlob(status, tra, &in->ablob, 0, nullptr));
|
||||
if (Blob == nullptr) {
|
||||
att.reset(context->getAttachment(status));
|
||||
tra.reset(context->getTransaction(status));
|
||||
blob.reset(att->openBlob(status, tra, &in->ablob, 0, nullptr));
|
||||
try {
|
||||
|
||||
if (blob == nullptr) {
|
||||
out->resultNull = FB_TRUE;
|
||||
out->result = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
std::vector<char> Buffer (MaxSegmentSize, 0);
|
||||
|
||||
std::vector<std::uint8_t> Buffer (MaxSegmentSize, 0);
|
||||
unsigned BytesRead = 0;
|
||||
|
||||
for (bool Eof = false; !Eof; )
|
||||
{
|
||||
switch (Blob->getSegment( status, MaxSegmentSize, Buffer.data(), &BytesRead))
|
||||
switch ( blob->getSegment ( status, MaxSegmentSize, Buffer.data(), &BytesRead))
|
||||
{
|
||||
case IStatus::RESULT_OK:
|
||||
case IStatus::RESULT_SEGMENT:
|
||||
{
|
||||
File.write( Buffer.data(), Buffer.size() );
|
||||
FileWriter.write( (char *) Buffer.data(), Buffer.size() );
|
||||
out->result += BytesRead;
|
||||
continue;
|
||||
}
|
||||
default:
|
||||
{
|
||||
Blob->close( status ); // will close interface
|
||||
Blob.release();
|
||||
blob->close( status ); // will close interface
|
||||
blob->release();
|
||||
Eof = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we have got this far then we have written the blob.
|
||||
// out->resultNULL ***must*** be set to false or else the function will return NULL
|
||||
out->resultNull = FB_FALSE;
|
||||
Buffer.clear();
|
||||
File.close();
|
||||
FileWriter.close();
|
||||
}
|
||||
catch ( const FbException& error )
|
||||
{
|
||||
throw Firebird::FbException(status, statusVector);
|
||||
}
|
||||
catch (...) {
|
||||
throw std::runtime_error("Error writing BLOB to file.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -20,15 +20,33 @@ execute procedure load_blob(3);
|
||||
execute procedure load_blob(4);
|
||||
commit;
|
||||
|
||||
select cast ( description as varchar(32) ) as DESCRIPTION
|
||||
select cast ( description as varchar(16) ) as DESCRIPTION
|
||||
, file_type
|
||||
, cast (left(source_file,32) as varchar(32)) as source_file
|
||||
, source_status
|
||||
-- , source_bytes D_BIGINT
|
||||
-- , target_file D_PATH
|
||||
-- , target_status D_STATUS
|
||||
-- , target_bytes D_BIGINT
|
||||
-- , the_blob D_BLOB
|
||||
, cast (left(target_file,32) as varchar(32)) as target_file
|
||||
, target_status
|
||||
, target_bytes
|
||||
from test_blobs;
|
||||
commit;
|
||||
|
||||
set term ^;
|
||||
shell
|
||||
mkdir --verbose /tmp/testudrkit
|
||||
ls /tmp/testudrkit
|
||||
^
|
||||
set term ;^
|
||||
|
||||
execute procedure save_blob(1, '/tmp/testudrkit/fb.conf' );
|
||||
execute procedure save_blob(2, '/tmp/testudrkit/fb.log' );
|
||||
commit;
|
||||
|
||||
select cast ( description as varchar(16) ) as DESCRIPTION
|
||||
, file_type
|
||||
, cast (left(source_file,32) as varchar(32)) as source_file
|
||||
, source_status
|
||||
, cast (left(target_file,32) as varchar(32)) as target_file
|
||||
, target_status
|
||||
, cast (target_bytes as varchar(16) ) as target_bytes
|
||||
from test_blobs;
|
||||
commit;
|
||||
|
@ -85,10 +85,39 @@ begin
|
||||
EXCEPTION E_BLOB_EXCEPTION 'Error updating test_blobs';
|
||||
end
|
||||
|
||||
end ^
|
||||
|
||||
set term ;^
|
||||
|
||||
|
||||
set term ^;
|
||||
create or alter procedure save_blob ( a_test_blob_id D_ID, atarget_file D_PATH ) sql security definer
|
||||
as
|
||||
declare theblob D_BLOB;
|
||||
declare result D_BIGINT;
|
||||
declare status D_STATUS;
|
||||
begin
|
||||
|
||||
select the_blob from test_blobs where test_blobs_id = :a_test_blob_id into :theblob;
|
||||
select SaveBlobToFile( :atarget_file, :theblob ) from rdb$database into :result;
|
||||
|
||||
if ( result >= 0 ) then
|
||||
status = 'W';
|
||||
else
|
||||
status = 'F';
|
||||
|
||||
update test_blobs
|
||||
set target_file = :atarget_file
|
||||
, target_bytes = :result
|
||||
, target_status = :status
|
||||
where test_blobs_id = :a_test_blob_id;
|
||||
when any do begin
|
||||
EXCEPTION E_BLOB_EXCEPTION 'Error updating test_blobs';
|
||||
end
|
||||
|
||||
|
||||
|
||||
end ^
|
||||
|
||||
set term ;^
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user