diff --git a/src/jrd/blb.cpp b/src/jrd/blb.cpp index 72bddcec6a..0138f30e93 100644 --- a/src/jrd/blb.cpp +++ b/src/jrd/blb.cpp @@ -2443,10 +2443,6 @@ static void move_from_string(thread_db* tdbb, const dsc* from_desc, dsc* to_desc ULONG blob_temp_id = blob->blb_temp_id; BLB_move(tdbb, &blob_desc, to_desc, field); - // finish if we're just moving values in descriptors - if (!field || field->nod_type != nod_field) - return; - // 14-June-2004. Nickolay Samofatov // The code below saves a lot of memory when bunches of records are // converted to blobs from strings. If BLB_move is materialized blob we @@ -2479,9 +2475,14 @@ static void move_from_string(thread_db* tdbb, const dsc* from_desc, dsc* to_desc } else { // But even in bad case when we cannot free blob immediately - // we may still bind lifetime of blob to current request. - if (!current->bli_request) { - current->bli_request = tdbb->tdbb_request; + // we may still bind lifetime of blob to current top level request. + if (!current->bli_request) + { + jrd_req* blob_request = tdbb->tdbb_request; + while (blob_request->req_caller) + blob_request = blob_request->req_caller; + + current->bli_request = blob_request; current->bli_request->req_blobs.add(blob_temp_id); } } diff --git a/src/jrd/exe.cpp b/src/jrd/exe.cpp index e45b6cc609..fde050f540 100644 --- a/src/jrd/exe.cpp +++ b/src/jrd/exe.cpp @@ -660,7 +660,8 @@ void EXE_receive(thread_db* tdbb, jrd_req* request, USHORT msg, USHORT length, - UCHAR* buffer) + UCHAR* buffer, + bool top_level) { /************************************** * @@ -738,6 +739,34 @@ void EXE_receive(thread_db* tdbb, else MOVE_FASTER((SCHAR *) request + message->nod_impure, buffer, length); + // ASF: temporary blobs returned to the client should not be released + // with the request, but in the transaction end. + if (top_level) + { + for (int i = 0; i < format->fmt_count; ++i) + { + const DSC* desc = &format->fmt_desc[i]; + + if (desc->isBlob()) + { + const bid* id = (bid*) + ((UCHAR*)request + message->nod_impure + (ULONG)(IPTR)desc->dsc_address); + + if (transaction->tra_blobs.locate(id->bid_temp_id())) + { + BlobIndex* current = &transaction->tra_blobs.current(); + + if (current->bli_request && + current->bli_request->req_blobs.locate(id->bid_temp_id())) + { + current->bli_request->req_blobs.fastRemove(); + current->bli_request = NULL; + } + } + } + } + } + execute_looper(tdbb, request, transaction, jrd_req::req_proceed); } //try diff --git a/src/jrd/exe_proto.h b/src/jrd/exe_proto.h index bd3c013879..56a7e3d3c6 100644 --- a/src/jrd/exe_proto.h +++ b/src/jrd/exe_proto.h @@ -35,7 +35,7 @@ namespace Jrd { void EXE_assignment(Jrd::thread_db*, Jrd::jrd_nod*); void EXE_execute_db_triggers(Jrd::thread_db*, Jrd::jrd_tra*, enum Jrd::jrd_req::req_ta); Jrd::jrd_req* EXE_find_request(Jrd::thread_db*, Jrd::jrd_req*, bool); -void EXE_receive(Jrd::thread_db*, Jrd::jrd_req*, USHORT, USHORT, UCHAR*); +void EXE_receive(Jrd::thread_db*, Jrd::jrd_req*, USHORT, USHORT, UCHAR*, bool = false); void EXE_send(Jrd::thread_db*, Jrd::jrd_req*, USHORT, USHORT, const UCHAR*); void EXE_start(Jrd::thread_db*, Jrd::jrd_req*, Jrd::jrd_tra*); void EXE_unwind(Jrd::thread_db*, Jrd::jrd_req*); diff --git a/src/jrd/jrd.cpp b/src/jrd/jrd.cpp index abf94719ff..ae0f125845 100644 --- a/src/jrd/jrd.cpp +++ b/src/jrd/jrd.cpp @@ -3179,7 +3179,7 @@ ISC_STATUS GDS_RECEIVE(ISC_STATUS * user_status, #endif EXE_receive(tdbb, request, msg_type, msg_length, - reinterpret_cast(msg)); + reinterpret_cast(msg), true); check_autocommit(request, tdbb);