@@ -477,7 +477,8 @@ void BLB_garbage_collect(thread_db* tdbb,
477477 bmGoing.set (number.getValue ());
478478 cntGoing++;
479479 }
480- else
480+ else if (!(relation->getPermanent ()->rel_flags & REL_temp_frame) ||
481+ blob->bid_internal .bid_relation_id )
481482 {
482483 // hvlad: blob_id in descriptor is not from our relation. Yes, it is
483484 // garbage in user data but we can handle it without bugcheck - just
@@ -520,7 +521,8 @@ void BLB_garbage_collect(thread_db* tdbb,
520521 return ;
521522 }
522523 }
523- else
524+ else if (!(relation->getPermanent ()->rel_flags & REL_temp_frame) ||
525+ blob->bid_internal .bid_relation_id )
524526 {
525527 gds__log (" staying blob (%ld:%ld) is not owned by relation (id = %d), ignored" ,
526528 blob->bid_quad .bid_quad_high , blob->bid_quad .bid_quad_low , relation->getId ());
@@ -1109,8 +1111,6 @@ void blb::move(thread_db* tdbb, dsc* from_desc, dsc* to_desc,
11091111 ERR_post (Arg::Gds (isc_read_only));
11101112 }
11111113
1112- RelationPages* relPages = relation->getPermanent ()->getPages (tdbb);
1113-
11141114 // If either the source value is null or the blob id itself is null
11151115 // (all zeros), then the blob is null.
11161116
@@ -1125,6 +1125,65 @@ void blb::move(thread_db* tdbb, dsc* from_desc, dsc* to_desc,
11251125 jrd_tra* transaction = request->req_transaction ;
11261126 transaction = transaction->getOuter ();
11271127
1128+ // Declared LTT records live only in an execution frame, while their BLOB
1129+ // values must be usable outside that frame. Keep the value as a transaction
1130+ // temporary BLOB instead of storing a frame-scoped permanent ID.
1131+ if (MetadataCache::isDeclaredLTT (relation->getId ()))
1132+ {
1133+ bool directMove = false ;
1134+
1135+ if (!needFilter && !source->bid_internal .bid_relation_id &&
1136+ transaction->tra_blobs ->locate (source->bid_temp_id ()))
1137+ {
1138+ const auto sourceIndex = &transaction->tra_blobs ->current ();
1139+
1140+ if (!sourceIndex->bli_materialized )
1141+ {
1142+ const auto sourceBlob = sourceIndex->bli_blob_object ;
1143+
1144+ if (!sourceBlob || !(sourceBlob->blb_flags & BLB_closed))
1145+ {
1146+ if (sourceBlob && (sourceBlob->blb_flags & BLB_close_on_read))
1147+ sourceBlob->BLB_close (tdbb);
1148+ else
1149+ ERR_post (Arg::Gds (isc_bad_segstr_id));
1150+ }
1151+
1152+ directMove = true ;
1153+ }
1154+ }
1155+
1156+ if (directMove)
1157+ *destination = *source;
1158+ else
1159+ {
1160+ UCharBuffer bpb;
1161+ if (needFilter)
1162+ BLB_gen_bpb_from_descs (from_desc, to_desc, bpb);
1163+
1164+ const auto dbb = tdbb->getDatabase ();
1165+ const USHORT pageSpace = dbb->dbb_page_manager .getTempPageSpaceID (tdbb);
1166+ blb* const blob = copy_blob (tdbb, source, destination,
1167+ bpb.getCount (), bpb.begin (), pageSpace);
1168+
1169+ blob->blb_flags |= BLB_dltt;
1170+ blob->blb_sub_type = to_desc->getBlobSubType ();
1171+ blob->blb_charset = to_desc->getCharSet ();
1172+ }
1173+
1174+ fb_assert (!destination->bid_internal .bid_relation_id );
1175+ fb_assert (transaction);
1176+
1177+ if (!transaction->tra_blobs ->locate (destination->bid_temp_id ()))
1178+ BUGCHECK (305 ); // msg 305 Blobs accounting is inconsistent
1179+
1180+ BlobIndex* const blobIndex = &transaction->tra_blobs ->current ();
1181+ fb_assert (!blobIndex->bli_materialized );
1182+ fb_assert (blobIndex->bli_blob_object );
1183+
1184+ return ;
1185+ }
1186+
11281187 // If the target is a view, this must be from a view update trigger.
11291188 // Just pass the blob id thru.
11301189
@@ -1150,6 +1209,8 @@ void blb::move(thread_db* tdbb, dsc* from_desc, dsc* to_desc,
11501209 return ;
11511210 }
11521211
1212+ RelationPages* relPages = relation->getPermanent ()->getPages (tdbb);
1213+
11531214 // If the source is a permanent blob, then the blob must be copied.
11541215 // Otherwise find the temporary blob referenced.
11551216
@@ -2602,6 +2663,9 @@ static void move_from_string(thread_db* tdbb, const dsc* from_desc, dsc* to_desc
26022663 temp_bid.clear ();
26032664 blb* blob = blb::create2 (tdbb, transaction, &temp_bid, bpb.getCount (), bpb.begin ());
26042665
2666+ if (relation && MetadataCache::isDeclaredLTT (relation->getId ()))
2667+ blob->blb_flags |= BLB_dltt;
2668+
26052669 dsc blob_desc;
26062670
26072671 blob_desc.dsc_scale = to_desc->dsc_scale ; // blob charset
0 commit comments