Skip to content

Commit a9a0f28

Browse files
committed
Fix #8595 - Unable to restore database to Firebird 6.0 (with schemas) from ODS 13.1 if database contains views with system tables used in subqueries.
1 parent e889ff1 commit a9a0f28

File tree

1 file changed

+98
-77
lines changed

1 file changed

+98
-77
lines changed

src/jrd/vio.cpp

Lines changed: 98 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ enum UndoDataRet
143143
udNone // record was not changed under current savepoint, use it as is
144144
};
145145

146+
static void gbak_put_search_system_schema_flag(thread_db* tdbb, record_param* rpb, jrd_tra* transaction);
147+
146148
static UndoDataRet get_undo_data(thread_db* tdbb, jrd_tra* transaction,
147149
record_param* rpb, MemoryPool* pool);
148150

@@ -3354,6 +3356,7 @@ bool VIO_modify(thread_db* tdbb, record_param* org_rpb, record_param* new_rpb, j
33543356
SET_TDBB(tdbb);
33553357

33563358
QualifiedName object_name;
3359+
const auto attachment = tdbb->getAttachment();
33573360
jrd_rel* relation = org_rpb->rpb_relation;
33583361

33593362
#ifdef VIO_DEBUG
@@ -3410,6 +3413,13 @@ bool VIO_modify(thread_db* tdbb, record_param* org_rpb, record_param* new_rpb, j
34103413

34113414
check_gbak_cheating_insupd(tdbb, relation, "UPDATE");
34123415

3416+
if (attachment->isGbak() &&
3417+
!(attachment->att_flags & ATT_gbak_restore_has_schema) &&
3418+
!(attachment->att_database->dbb_flags & DBB_creating))
3419+
{
3420+
gbak_put_search_system_schema_flag(tdbb, new_rpb, transaction);
3421+
}
3422+
34133423
// If we're about to modify a system relation, check to make sure
34143424
// everything is completely kosher.
34153425

@@ -4109,7 +4119,9 @@ void VIO_store(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
41094119

41104120
check_gbak_cheating_insupd(tdbb, relation, "INSERT");
41114121

4112-
if (attachment->isGbak() && !(attachment->att_flags & ATT_gbak_restore_has_schema))
4122+
if (attachment->isGbak() &&
4123+
!(attachment->att_flags & ATT_gbak_restore_has_schema) &&
4124+
!(attachment->att_database->dbb_flags & DBB_creating))
41134125
{
41144126
struct ObjTypeFieldId
41154127
{
@@ -4297,82 +4309,7 @@ void VIO_store(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
42974309
desc2.setNull();
42984310
}
42994311

4300-
static const std::unordered_map<USHORT, std::vector<USHORT>> schemaBlrFields = {
4301-
{rel_args, {f_arg_default}},
4302-
{rel_fields, {f_fld_v_blr, f_fld_computed, f_fld_default, f_fld_missing}},
4303-
{rel_funs, {f_fun_blr}},
4304-
{rel_indices, {f_idx_exp_blr, f_idx_cond_blr}},
4305-
{rel_prc_prms, {f_prm_default}},
4306-
{rel_procedures, {f_prc_blr}},
4307-
{rel_relations, {f_rel_blr}},
4308-
{rel_rfr, {f_rfr_default}},
4309-
{rel_triggers, {f_trg_blr}}
4310-
};
4311-
4312-
static const UCHAR bpb[] = {
4313-
isc_bpb_version1,
4314-
isc_bpb_type, 1, isc_bpb_type_stream
4315-
};
4316-
4317-
if (const auto relBlrFields = schemaBlrFields.find(relation->rel_id); relBlrFields != schemaBlrFields.end())
4318-
{
4319-
UCHAR buffer[BUFFER_MEDIUM];
4320-
4321-
for (const auto field : relBlrFields->second)
4322-
{
4323-
if (EVL_field(0, rpb->rpb_record, field, &desc))
4324-
{
4325-
AutoBlb blob(tdbb, blb::open(tdbb, transaction, reinterpret_cast<bid*>(desc.dsc_address)));
4326-
bid newBid;
4327-
const auto newBlob = blb::create2(tdbb, transaction, &newBid, sizeof(bpb), bpb);
4328-
bool firstSegment = true;
4329-
UCHAR newHeader[] = {
4330-
0,
4331-
blr_flags,
4332-
blr_flags_search_system_schema,
4333-
0, 0,
4334-
blr_end
4335-
};
4336-
4337-
while (!(blob->blb_flags & BLB_eof))
4338-
{
4339-
const auto len = blob->BLB_get_data(tdbb, buffer, sizeof(buffer), false);
4340-
4341-
if (len > 1 && firstSegment)
4342-
{
4343-
newHeader[0] = buffer[0];
4344-
fb_assert(newHeader[0] == blr_version4 || newHeader[0] == blr_version5);
4345-
4346-
if ((newHeader[0] == blr_version4 || newHeader[0] == blr_version5) &&
4347-
buffer[1] != blr_flags)
4348-
{
4349-
newBlob->BLB_put_data(tdbb, newHeader, sizeof(newHeader));
4350-
newBlob->BLB_put_data(tdbb, buffer + 1, len - 1);
4351-
4352-
firstSegment = false;
4353-
}
4354-
else
4355-
{
4356-
newBid.clear();
4357-
break;
4358-
}
4359-
}
4360-
else
4361-
newBlob->BLB_put_data(tdbb, buffer, len);
4362-
}
4363-
4364-
newBlob->BLB_close(tdbb);
4365-
4366-
if (!newBid.isEmpty())
4367-
{
4368-
desc2.makeBlob(isc_blob_untyped, 0, reinterpret_cast<ISC_QUAD*>(&newBid));
4369-
blb::move(tdbb, &desc2, &desc, relation, rpb->rpb_record, field);
4370-
}
4371-
}
4372-
}
4373-
}
4374-
4375-
desc2.setNull();
4312+
gbak_put_search_system_schema_flag(tdbb, rpb, transaction);
43764313
}
43774314

43784315
desc.setNull();
@@ -5973,6 +5910,90 @@ void Database::exceptionHandler(const Firebird::Exception& ex,
59735910
}
59745911

59755912

5913+
static void gbak_put_search_system_schema_flag(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
5914+
{
5915+
static const std::unordered_map<USHORT, std::vector<USHORT>> schemaBlrFields = {
5916+
{rel_args, {f_arg_default}},
5917+
{rel_fields, {f_fld_v_blr, f_fld_computed, f_fld_default, f_fld_missing}},
5918+
{rel_funs, {f_fun_blr}},
5919+
{rel_indices, {f_idx_exp_blr, f_idx_cond_blr}},
5920+
{rel_prc_prms, {f_prm_default}},
5921+
{rel_procedures, {f_prc_blr}},
5922+
{rel_relations, {f_rel_blr}},
5923+
{rel_rfr, {f_rfr_default}},
5924+
{rel_triggers, {f_trg_blr}}
5925+
};
5926+
5927+
static const UCHAR bpb[] = {
5928+
isc_bpb_version1,
5929+
isc_bpb_type, 1, isc_bpb_type_stream
5930+
};
5931+
5932+
SET_TDBB(tdbb);
5933+
5934+
const auto relation = rpb->rpb_relation;
5935+
dsc desc, desc2;
5936+
5937+
if (const auto relBlrFields = schemaBlrFields.find(relation->rel_id); relBlrFields != schemaBlrFields.end())
5938+
{
5939+
UCHAR buffer[BUFFER_MEDIUM];
5940+
5941+
for (const auto field : relBlrFields->second)
5942+
{
5943+
if (EVL_field(0, rpb->rpb_record, field, &desc))
5944+
{
5945+
AutoBlb blob(tdbb, blb::open(tdbb, transaction, reinterpret_cast<bid*>(desc.dsc_address)));
5946+
bid newBid;
5947+
const auto newBlob = blb::create2(tdbb, transaction, &newBid, sizeof(bpb), bpb);
5948+
bool firstSegment = true;
5949+
UCHAR newHeader[] = {
5950+
0,
5951+
blr_flags,
5952+
blr_flags_search_system_schema,
5953+
0, 0,
5954+
blr_end
5955+
};
5956+
5957+
while (!(blob->blb_flags & BLB_eof))
5958+
{
5959+
const auto len = blob->BLB_get_data(tdbb, buffer, sizeof(buffer), false);
5960+
5961+
if (len > 1 && firstSegment)
5962+
{
5963+
newHeader[0] = buffer[0];
5964+
fb_assert(newHeader[0] == blr_version4 || newHeader[0] == blr_version5);
5965+
5966+
if ((newHeader[0] == blr_version4 || newHeader[0] == blr_version5) &&
5967+
buffer[1] != blr_flags)
5968+
{
5969+
newBlob->BLB_put_data(tdbb, newHeader, sizeof(newHeader));
5970+
newBlob->BLB_put_data(tdbb, buffer + 1, len - 1);
5971+
5972+
firstSegment = false;
5973+
}
5974+
else
5975+
{
5976+
newBid.clear();
5977+
break;
5978+
}
5979+
}
5980+
else
5981+
newBlob->BLB_put_data(tdbb, buffer, len);
5982+
}
5983+
5984+
newBlob->BLB_close(tdbb);
5985+
5986+
if (!newBid.isEmpty())
5987+
{
5988+
desc2.makeBlob(isc_blob_untyped, 0, reinterpret_cast<ISC_QUAD*>(&newBid));
5989+
blb::move(tdbb, &desc2, &desc, relation, rpb->rpb_record, field);
5990+
}
5991+
}
5992+
}
5993+
}
5994+
}
5995+
5996+
59765997
static UndoDataRet get_undo_data(thread_db* tdbb, jrd_tra* transaction,
59775998
record_param* rpb, MemoryPool* pool)
59785999
/**********************************************************

0 commit comments

Comments
 (0)