8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-24 01:23:03 +01:00

Fixed CORE-3138: Internal error or crash occurs when accessing any MON$ table after altering its structure.

This commit is contained in:
dimitr 2011-02-14 11:10:58 +00:00
parent 3bb7d22126
commit f2c890e1fc
3 changed files with 45 additions and 24 deletions

View File

@ -614,31 +614,48 @@ DatabaseSnapshot::~DatabaseSnapshot()
}
RecordBuffer* DatabaseSnapshot::getData(const jrd_rel* relation) const
const DatabaseSnapshot::RelationData* DatabaseSnapshot::getRelationData(int id) const
{
fb_assert(relation);
for (size_t i = 0; i < snapshot.getCount(); i++)
{
if (snapshot[i].rel_id == relation->rel_id)
return snapshot[i].data;
if (snapshot[i].rel_id == id)
return &snapshot[i];
}
return NULL;
}
const Format* DatabaseSnapshot::getFormat(const jrd_rel* relation) const
{
fb_assert(relation);
const RelationData* const relData = getRelationData(relation->rel_id);
return relData ? relData->format : NULL;
}
RecordBuffer* DatabaseSnapshot::getData(const jrd_rel* relation) const
{
fb_assert(relation);
const RelationData* const relData = getRelationData(relation->rel_id);
return relData ? relData->data : NULL;
}
RecordBuffer* DatabaseSnapshot::allocBuffer(thread_db* tdbb, MemoryPool& pool, int rel_id)
{
jrd_rel* relation = MET_lookup_relation_id(tdbb, rel_id, false);
jrd_rel* const relation = MET_lookup_relation_id(tdbb, rel_id, false);
fb_assert(relation);
MET_scan_relation(tdbb, relation);
fb_assert(relation->isVirtual());
Format* format = MET_current(tdbb, relation);
const Format* const format = MET_current(tdbb, relation);
fb_assert(format);
RecordBuffer* buffer = FB_NEW(pool) RecordBuffer(pool, format);
RelationData data = {relation->rel_id, buffer};
RecordBuffer* const buffer = FB_NEW(pool) RecordBuffer(pool, format);
RelationData data = {relation->rel_id, format, buffer};
snapshot.add(data);
return buffer;
@ -662,9 +679,18 @@ void DatabaseSnapshot::putField(thread_db* tdbb, Record* record, const DumpField
fb_assert(record);
const Format* const format = record->rec_format;
fb_assert(format && field.id < format->fmt_count);
fb_assert(format);
dsc to_desc;
if (field.id < format->fmt_count)
{
to_desc = format->fmt_desc[field.id];
}
if (to_desc.isUnknown())
return;
dsc to_desc = format->fmt_desc[field.id];
to_desc.dsc_address += (IPTR) record->rec_data;
if (field.type == VALUE_GLOBAL_ID)

View File

@ -180,6 +180,7 @@ class DatabaseSnapshot
struct RelationData
{
int rel_id;
const Format* format;
RecordBuffer* data;
};
@ -318,6 +319,7 @@ private:
public:
~DatabaseSnapshot();
const Format* getFormat(const jrd_rel*) const;
RecordBuffer* getData(const jrd_rel*) const;
static DatabaseSnapshot* create(thread_db*);
@ -330,6 +332,7 @@ private:
RecordBuffer* allocBuffer(thread_db*, MemoryPool&, int);
void clearRecord(Record*);
void putField(thread_db*, Record*, const DumpField&, int&, bool = false);
const RelationData* getRelationData(int id) const;
static void dumpData(thread_db*);

View File

@ -141,21 +141,13 @@ void VirtualTable::open(thread_db* tdbb, RecordSource* rsb)
record_param* const rpb = &request->req_rpb[rsb->rsb_stream];
irsb_virtual* const impure = (irsb_virtual*) ((UCHAR *) request + rsb->rsb_impure);
const Record* const record = rpb->rpb_record;
const Format* format = NULL;
if (!record || !record->rec_format)
{
format = MET_current(tdbb, relation);
VIO_record(tdbb, rpb, format, request->req_pool);
}
else {
format = record->rec_format;
}
DatabaseSnapshot* const snapshot = DatabaseSnapshot::create(tdbb);
impure->irsb_record_buffer = snapshot->getData(relation);
const Format* const format = snapshot->getFormat(relation);
VIO_record(tdbb, rpb, format, request->req_pool);
rpb->rpb_number.setValue(BOF_NUMBER);
DatabaseSnapshot* snapshot = DatabaseSnapshot::create(tdbb);
impure->irsb_record_buffer = snapshot->getData(relation);
}