@@ -1312,6 +1312,8 @@ void Blob::getInfo(CheckStatusWrapper* status,
13121312 if (blob->rbl_info .getLocalInfo (itemsLength, items, bufferLength, buffer))
13131313 return ;
13141314
1315+ fb_assert (!blob->isCached ());
1316+
13151317 rem_port* port = rdb->rdb_port ;
13161318 RefMutexGuard portGuard (*port->port_sync , FB_FUNCTION);
13171319
@@ -1353,7 +1355,8 @@ void Blob::freeClientData(CheckStatusWrapper* status, bool force)
13531355
13541356 try
13551357 {
1356- release_object (status, rdb, op_cancel_blob, blob->rbl_id );
1358+ if (!blob->isCached ())
1359+ release_object (status, rdb, op_cancel_blob, blob->rbl_id );
13571360 }
13581361 catch (const Exception&)
13591362 {
@@ -1426,10 +1429,13 @@ void Blob::internalClose(CheckStatusWrapper* status)
14261429
14271430 if ((blob->rbl_flags & Rbl::CREATE) && blob->rbl_ptr != blob->rbl_buffer )
14281431 {
1432+ fb_assert (!blob->isCached ());
1433+
14291434 send_blob (status, blob, 0 , NULL );
14301435 }
14311436
1432- release_object (status, rdb, op_close_blob, blob->rbl_id );
1437+ if (!blob->isCached ())
1438+ release_object (status, rdb, op_close_blob, blob->rbl_id );
14331439 release_blob (blob);
14341440 blob = NULL ;
14351441 }
@@ -1847,14 +1853,13 @@ IBlob* Attachment::createBlob(CheckStatusWrapper* status, ITransaction* apiTra,
18471853 p_blob->p_blob_bpb .cstr_address = NULL ;
18481854
18491855 Rbl* blob = FB_NEW Rbl ();
1850- *blob_id = packet->p_resp .p_resp_blob_id ;
1856+ blob-> rbl_blob_id = *blob_id = packet->p_resp .p_resp_blob_id ;
18511857 blob->rbl_rdb = rdb;
18521858 blob->rbl_rtr = transaction;
18531859 blob->rbl_id = packet->p_resp .p_resp_object ;
18541860 blob->rbl_flags |= Rbl::CREATE;
18551861 SET_OBJECT (rdb, blob, blob->rbl_id );
1856- blob->rbl_next = transaction->rtr_blobs ;
1857- transaction->rtr_blobs = blob;
1862+ transaction->rtr_blobs .add (blob);
18581863
18591864 IBlob* b = FB_NEW Blob (blob);
18601865 b->addRef ();
@@ -3578,8 +3583,21 @@ ITransaction* Statement::execute(CheckStatusWrapper* status, ITransaction* apiTr
35783583 if (out_msg_length)
35793584 port->port_statement ->rsr_message ->msg_address = out_msg;
35803585
3586+ // Prepare to receive inline blobs
3587+ P_INLINE_BLOB* p_blob = &packet->p_inline_blob ;
3588+ UCHAR blobInfo[64 ];
3589+
3590+ UsePreallocatedBuffer guardBlobInfo (p_blob->p_blob_info , sizeof (blobInfo), blobInfo);
3591+
35813592 receive_packet (port, packet);
35823593
3594+ while (packet->p_operation == op_inline_blob)
3595+ {
3596+ fb_assert (transaction);
3597+ transaction->setupInlineBlob (p_blob);
3598+ receive_packet (port, packet);
3599+ }
3600+
35833601 if (packet->p_operation != op_sql_response)
35843602 REMOTE_check_response (status, rdb, packet);
35853603 else
@@ -3940,8 +3958,21 @@ ITransaction* Attachment::execute(CheckStatusWrapper* status, ITransaction* apiT
39403958 if (in_msg_length || out_msg_length)
39413959 port->port_statement ->rsr_message ->msg_address = out_msg;
39423960
3961+ // Prepare to receive inline blobs
3962+ P_INLINE_BLOB* p_blob = &packet->p_inline_blob ;
3963+ UCHAR blobInfo[64 ];
3964+
3965+ UsePreallocatedBuffer guardBlobInfo (p_blob->p_blob_info , sizeof (blobInfo), blobInfo);
3966+
39433967 receive_packet (rdb->rdb_port , packet);
39443968
3969+ while (packet->p_operation == op_inline_blob)
3970+ {
3971+ fb_assert (transaction);
3972+ transaction->setupInlineBlob (p_blob);
3973+ receive_packet (port, packet);
3974+ }
3975+
39453976 if (packet->p_operation != op_sql_response)
39463977 REMOTE_check_response (status, rdb, packet);
39473978 else
@@ -5507,6 +5538,8 @@ int Blob::getSegment(CheckStatusWrapper* status, unsigned int bufferLength, void
55075538 break ;
55085539 }
55095540
5541+ fb_assert (!blob->isCached ());
5542+
55105543 // Preparatory to asking for more data, use input buffer length
55115544 // to cue more efficient blob buffering.
55125545
@@ -5668,6 +5701,20 @@ IBlob* Attachment::openBlob(CheckStatusWrapper* status, ITransaction* apiTra, IS
56685701 Rtr* transaction = remoteTransaction (apiTra);
56695702 CHECK_HANDLE (transaction, isc_bad_trans_handle);
56705703
5704+ if (transaction->rtr_blobs .locate (*id))
5705+ {
5706+ Rbl* blob = transaction->rtr_blobs .current ();
5707+
5708+ if (!bpb_length)
5709+ {
5710+ Blob* iBlob = FB_NEW Blob (blob);
5711+ iBlob->addRef ();
5712+ return iBlob;
5713+ }
5714+
5715+ release_blob (blob);
5716+ }
5717+
56715718 // Validate data length
56725719
56735720 CHECK_LENGTH (port, bpb_length);
@@ -5769,10 +5816,10 @@ IBlob* Attachment::openBlob(CheckStatusWrapper* status, ITransaction* apiTra, IS
57695816 Rbl* blob = FB_NEW Rbl;
57705817 blob->rbl_rdb = rdb;
57715818 blob->rbl_rtr = transaction;
5819+ blob->rbl_blob_id = *id;
57725820 blob->rbl_id = packet->p_resp .p_resp_object ;
57735821 SET_OBJECT (rdb, blob, blob->rbl_id );
5774- blob->rbl_next = transaction->rtr_blobs ;
5775- transaction->rtr_blobs = blob;
5822+ transaction->rtr_blobs .add (blob);
57765823
57775824 Blob* iBlob = FB_NEW Blob (blob);
57785825 iBlob->addRef ();
@@ -6619,6 +6666,11 @@ int Blob::seek(CheckStatusWrapper* status, int mode, int offset)
66196666
66206667 CHECK_HANDLE (blob, isc_bad_segstr_handle);
66216668
6669+ if (blob->isCached ())
6670+ {
6671+ Arg::Gds (isc_wish_list).raise ();
6672+ }
6673+
66226674 Rdb* rdb = blob->rbl_rdb ;
66236675 CHECK_HANDLE (rdb, isc_bad_db_handle);
66246676 rem_port* port = rdb->rdb_port ;
@@ -7843,6 +7895,12 @@ static void batch_dsql_fetch(rem_port* port,
78437895 // Avoid damaging preallocated buffer for response data
78447896 UseStandardBuffer guard (packet->p_resp .p_resp_data );
78457897
7898+ // Prepare to receive inline blobs
7899+ P_INLINE_BLOB* p_blob = &packet->p_inline_blob ;
7900+ UCHAR blobInfo[64 ];
7901+
7902+ UsePreallocatedBuffer guardBlobInfo (p_blob->p_blob_info , sizeof (blobInfo), blobInfo);
7903+
78467904 statement->rsr_flags .set (Rsr::FETCHED);
78477905 while (true )
78487906 {
@@ -7878,6 +7936,17 @@ static void batch_dsql_fetch(rem_port* port,
78787936 throw ;
78797937 }
78807938
7939+ if (packet->p_operation == op_inline_blob)
7940+ {
7941+ fb_assert (!statement->rsr_rtr || statement->rsr_rtr ->rtr_id == p_blob->p_tran_id );
7942+
7943+ Rtr* transaction = statement->rsr_rtr ?
7944+ statement->rsr_rtr : port->port_objects [p_blob->p_tran_id ];
7945+
7946+ transaction->setupInlineBlob (p_blob);
7947+ continue ;
7948+ }
7949+
78817950 if (packet->p_operation != op_fetch_response)
78827951 {
78837952 statement->rsr_flags .set (Rsr::STREAM_ERR);
@@ -9217,16 +9286,12 @@ static void release_blob( Rbl* blob)
92179286 **************************************/
92189287 Rtr* transaction = blob->rbl_rtr ;
92199288 Rdb* rdb = blob->rbl_rdb ;
9220- rdb->rdb_port ->releaseObject (blob->rbl_id );
92219289
9222- for (Rbl** p = &transaction->rtr_blobs ; *p; p = &(*p)->rbl_next )
9223- {
9224- if (*p == blob)
9225- {
9226- *p = blob->rbl_next ;
9227- break ;
9228- }
9229- }
9290+ if (!blob->isCached ())
9291+ rdb->rdb_port ->releaseObject (blob->rbl_id );
9292+
9293+ if (transaction->rtr_blobs .locate (blob->rbl_blob_id ))
9294+ transaction->rtr_blobs .fastRemove ();
92309295
92319296 delete blob;
92329297}
@@ -9384,8 +9449,8 @@ static void release_transaction( Rtr* transaction)
93849449 Rdb* rdb = transaction->rtr_rdb ;
93859450 rdb->rdb_port ->releaseObject (transaction->rtr_id );
93869451
9387- while (transaction->rtr_blobs )
9388- release_blob (transaction->rtr_blobs );
9452+ while (transaction->rtr_blobs . getFirst () )
9453+ release_blob (transaction->rtr_blobs . current () );
93899454
93909455 for (Rtr** p = &rdb->rdb_transactions ; *p; p = &(*p)->rtr_next )
93919456 {
@@ -9433,6 +9498,8 @@ static void send_blob(CheckStatusWrapper* status,
94339498 * Actually send blob data (which might be buffered)
94349499 *
94359500 **************************************/
9501+ fb_assert (!blob->isCached ());
9502+
94369503 Rdb* rdb = blob->rbl_rdb ;
94379504 PACKET* packet = &rdb->rdb_packet ;
94389505 packet->p_operation = op_put_segment;
0 commit comments