Skip to content

Commit 92bad46

Browse files
committed
Put DLTT blobs in tra_blobs
1 parent e90e917 commit 92bad46

5 files changed

Lines changed: 81 additions & 9 deletions

File tree

src/jrd/BlobUtil.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ namespace
5353
status_exception::raise(Arg::Gds(isc_bad_segstr_id));
5454

5555
const auto blobIndex = &transaction->tra_blobs->current();
56-
fb_assert(blobIndex->bli_blob_object);
56+
fb_assert(blobIndex->bli_materialized || blobIndex->bli_blob_object);
5757

5858
return blobIndex;
5959
}
@@ -72,7 +72,7 @@ IExternalResultSet* BlobUtilPackage::cancelBlobProcedure(ThrowStatusExceptionWra
7272

7373
if (const auto blobIdx = getTempBlobIndexFromId(tdbb, blobId))
7474
{
75-
if (blobIdx->bli_materialized)
75+
if (blobIdx->bli_materialized || (blobIdx->bli_blob_object->blb_flags & BLB_dltt))
7676
status_exception::raise(Arg::Gds(isc_bad_segstr_id));
7777

7878
const auto blob = blobIdx->bli_blob_object;
@@ -108,7 +108,9 @@ void BlobUtilPackage::isWritableFunction(ThrowStatusExceptionWrapper* status,
108108

109109
if (const auto blobIdx = getTempBlobIndexFromId(tdbb, blobId))
110110
{
111-
if (!blobIdx->bli_materialized && (blobIdx->bli_blob_object->blb_flags & BLB_close_on_read))
111+
if (!blobIdx->bli_materialized &&
112+
!(blobIdx->bli_blob_object->blb_flags & BLB_dltt) &&
113+
(blobIdx->bli_blob_object->blb_flags & BLB_close_on_read))
112114
{
113115
out->boolean = FB_TRUE;
114116
return;

src/jrd/Statement.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1064,7 +1064,7 @@ Request* Request::getLocalTableRequest(bool outerDecl)
10641064

10651065
if (outerDecl)
10661066
{
1067-
while (request->req_caller)
1067+
while (request->getStatement()->parentStatement)
10681068
request = request->req_caller;
10691069
}
10701070

src/jrd/blb.cpp

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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

src/jrd/blb.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ class blb : public pool_alloc<type_blb>
104104
void BLB_check_well_formed(thread_db*, const dsc* desc);
105105
bool BLB_close(thread_db*);
106106
static blb* create(thread_db*, jrd_tra*, bid*);
107-
static blb* create2(thread_db*, jrd_tra*, bid*, USHORT, const UCHAR*, bool = false);
107+
static blb* create2(thread_db*, jrd_tra*, bid*, USHORT, const UCHAR*, bool = false);
108108
static blb* get_array(thread_db*, jrd_tra*, const bid*, Ods::InternalArrayDesc*);
109109
ULONG BLB_get_data(thread_db*, UCHAR*, SLONG, bool = true);
110110
USHORT BLB_get_segment(thread_db*, void*, USHORT);
@@ -183,6 +183,7 @@ inline constexpr int BLB_seek = 32; // Seek is pending
183183
inline constexpr int BLB_large_scan = 64; // Blob is larger than page buffer cache
184184
inline constexpr int BLB_close_on_read = 128; // Temporary blob is not closed until read
185185
inline constexpr int BLB_user = 256; // User-defined blob
186+
inline constexpr int BLB_dltt = 512; // Blob stored in a declared local temporary table
186187

187188
/* Blob levels are:
188189

src/jrd/met.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,11 @@ class MetadataCache : public Firebird::PermanentStorage
457457
return (id >= MIN_LTT_ID && id <= MAX_LTT_ID);
458458
}
459459

460+
static bool isDeclaredLTT(MetaId id)
461+
{
462+
return (id >= MIN_DECLARED_LTT_ID && id <= MAX_DECLARED_LTT_ID);
463+
}
464+
460465

461466
private:
462467
static jrd_rel* getLtt(thread_db* tdbb, MetaId id);

0 commit comments

Comments
 (0)