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

Avoid using rpb in places where only record is needed, this also fixes a regression after #6995

This commit is contained in:
Dmitry Yemanov 2021-11-25 10:33:29 +03:00
parent 3022cf7f95
commit 5ca78a00f9
7 changed files with 67 additions and 61 deletions

View File

@ -7103,10 +7103,11 @@ const StmtNode* ModifyNode::modify(thread_db* tdbb, jrd_req* request, WhichTrigg
newRpb->rpb_length = newFormat->fmt_length; newRpb->rpb_length = newFormat->fmt_length;
newRpb->rpb_format_number = newFormat->fmt_version; newRpb->rpb_format_number = newFormat->fmt_version;
if (!orgRpb->rpb_record) Record* orgRecord = orgRpb->rpb_record;
if (!orgRecord)
{ {
const Format* const orgFormat = newFormat; const Format* const orgFormat = newFormat;
Record* const orgRecord = VIO_record(tdbb, orgRpb, orgFormat, tdbb->getDefaultPool()); orgRecord = VIO_record(tdbb, orgRpb, orgFormat, tdbb->getDefaultPool());
orgRpb->rpb_address = orgRecord->getData(); orgRpb->rpb_address = orgRecord->getData();
orgRpb->rpb_length = orgFormat->fmt_length; orgRpb->rpb_length = orgFormat->fmt_length;
orgRpb->rpb_format_number = orgFormat->fmt_version; orgRpb->rpb_format_number = orgFormat->fmt_version;
@ -7114,7 +7115,7 @@ const StmtNode* ModifyNode::modify(thread_db* tdbb, jrd_req* request, WhichTrigg
// Copy the original record to the new record // Copy the original record to the new record
VIO_copy_record(tdbb, orgRpb, newRpb); VIO_copy_record(tdbb, relation, orgRecord, newRecord);
newRpb->rpb_number = orgRpb->rpb_number; newRpb->rpb_number = orgRpb->rpb_number;
newRpb->rpb_number.setValid(true); newRpb->rpb_number.setValid(true);

View File

@ -87,7 +87,7 @@ static ArrayField* find_array(jrd_tra*, const bid*);
static BlobFilter* find_filter(thread_db*, SSHORT, SSHORT); static BlobFilter* find_filter(thread_db*, SSHORT, SSHORT);
//static blob_page* get_next_page(thread_db*, blb*, WIN *); //static blob_page* get_next_page(thread_db*, blb*, WIN *);
//static void insert_page(thread_db*, blb*); //static void insert_page(thread_db*, blb*);
static void move_from_string(Jrd::thread_db*, const dsc*, dsc*, const record_param* rpb, USHORT fieldId); static void move_from_string(Jrd::thread_db*, const dsc*, dsc*, jrd_rel*, Record*, USHORT);
static void move_to_string(Jrd::thread_db*, dsc*, dsc*); static void move_to_string(Jrd::thread_db*, dsc*, dsc*);
static void slice_callback(array_slice*, ULONG, dsc*); static void slice_callback(array_slice*, ULONG, dsc*);
static blb* store_array(thread_db*, jrd_tra*, bid*); static blb* store_array(thread_db*, jrd_tra*, bid*);
@ -949,7 +949,8 @@ SLONG blb::BLB_lseek(USHORT mode, SLONG offset)
// which in turn calls blb::create2 that writes in the blob id. Although the // which in turn calls blb::create2 that writes in the blob id. Although the
// compiler allows to modify from_desc->dsc_address' contents when from_desc is // compiler allows to modify from_desc->dsc_address' contents when from_desc is
// constant, this is misleading so I didn't make the source descriptor constant. // constant, this is misleading so I didn't make the source descriptor constant.
void blb::move(thread_db* tdbb, dsc* from_desc, dsc* to_desc, const record_param* rpb, USHORT fieldId) void blb::move(thread_db* tdbb, dsc* from_desc, dsc* to_desc,
jrd_rel* relation, Record* record, USHORT fieldId)
{ {
/************************************** /**************************************
* *
@ -980,7 +981,7 @@ void blb::move(thread_db* tdbb, dsc* from_desc, dsc* to_desc, const record_param
if (!DTYPE_IS_BLOB_OR_QUAD(from_desc->dsc_dtype)) if (!DTYPE_IS_BLOB_OR_QUAD(from_desc->dsc_dtype))
{ {
// anything that can be copied into a string can be copied into a blob // anything that can be copied into a string can be copied into a blob
move_from_string(tdbb, from_desc, to_desc, rpb, fieldId); move_from_string(tdbb, from_desc, to_desc, relation, record, fieldId);
return; return;
} }
} }
@ -996,7 +997,7 @@ void blb::move(thread_db* tdbb, dsc* from_desc, dsc* to_desc, const record_param
// We should not materialize the blob if the destination field // We should not materialize the blob if the destination field
// stream (nod_union, for example) doesn't have a relation. // stream (nod_union, for example) doesn't have a relation.
const bool simpleMove = !rpb || (rpb->rpb_relation == NULL); const bool simpleMove = (relation == NULL);
// Use local copy of source blob id to not change contents of from_desc in // Use local copy of source blob id to not change contents of from_desc in
// a case when it points to materialized temporary blob (see below for // a case when it points to materialized temporary blob (see below for
@ -1052,14 +1053,12 @@ void blb::move(thread_db* tdbb, dsc* from_desc, dsc* to_desc, const record_param
} }
jrd_req* request = tdbb->getRequest(); jrd_req* request = tdbb->getRequest();
jrd_rel* relation = rpb->rpb_relation;
if (relation->isVirtual()) { if (relation->isVirtual()) {
ERR_post(Arg::Gds(isc_read_only)); ERR_post(Arg::Gds(isc_read_only));
} }
RelationPages* relPages = relation->getPages(tdbb); RelationPages* relPages = relation->getPages(tdbb);
Record* record = rpb->rpb_record;
// If either the source value is null or the blob id itself is null // If either the source value is null or the blob id itself is null
// (all zeros), then the blob is null. // (all zeros), then the blob is null.
@ -2502,7 +2501,7 @@ void blb::insert_page(thread_db* tdbb)
static void move_from_string(thread_db* tdbb, const dsc* from_desc, dsc* to_desc, static void move_from_string(thread_db* tdbb, const dsc* from_desc, dsc* to_desc,
const record_param* rpb, USHORT fieldId) jrd_rel* relation, Record* record, USHORT fieldId)
{ {
/************************************** /**************************************
* *
@ -2558,7 +2557,7 @@ static void move_from_string(thread_db* tdbb, const dsc* from_desc, dsc* to_desc
blob->BLB_put_segment(tdbb, fromstr, length); blob->BLB_put_segment(tdbb, fromstr, length);
blob->BLB_close(tdbb); blob->BLB_close(tdbb);
ULONG blob_temp_id = blob->getTempId(); ULONG blob_temp_id = blob->getTempId();
blb::move(tdbb, &blob_desc, to_desc, rpb, fieldId); blb::move(tdbb, &blob_desc, to_desc, relation, record, fieldId);
// 14-June-2004. Nickolay Samofatov // 14-June-2004. Nickolay Samofatov
// The code below saves a lot of memory when bunches of records are // The code below saves a lot of memory when bunches of records are

View File

@ -56,7 +56,7 @@ class jrd_tra;
class vcl; class vcl;
class thread_db; class thread_db;
struct win; struct win;
struct record_param; class Record;
class ArrayField; class ArrayField;
struct impure_value; struct impure_value;
@ -109,7 +109,7 @@ public:
static SLONG get_slice(Jrd::thread_db*, Jrd::jrd_tra*, const Jrd::bid*, const UCHAR*, USHORT, static SLONG get_slice(Jrd::thread_db*, Jrd::jrd_tra*, const Jrd::bid*, const UCHAR*, USHORT,
const UCHAR*, SLONG, UCHAR*); const UCHAR*, SLONG, UCHAR*);
SLONG BLB_lseek(USHORT, SLONG); SLONG BLB_lseek(USHORT, SLONG);
static void move(thread_db* tdbb, dsc* from_desc, dsc* to_desc, const record_param* rpb = NULL, USHORT fieldId = 0); static void move(thread_db* tdbb, dsc* from_desc, dsc* to_desc, jrd_rel* relation = nullptr, Record* record = nullptr, USHORT fieldId = 0);
static blb* open(thread_db*, jrd_tra*, const bid*); static blb* open(thread_db*, jrd_tra*, const bid*);
static blb* open2(thread_db*, jrd_tra*, const bid*, USHORT, const UCHAR*, bool = false); static blb* open2(thread_db*, jrd_tra*, const bid*, USHORT, const UCHAR*, bool = false);
void BLB_put_data(thread_db*, const UCHAR*, SLONG); void BLB_put_data(thread_db*, const UCHAR*, SLONG);

View File

@ -399,21 +399,25 @@ void EXE_assignment(thread_db* tdbb, const ValueExprNode* to, dsc* from_desc, bo
// ASF: Don't let MOV_move call blb::move because MOV // ASF: Don't let MOV_move call blb::move because MOV
// will not pass the destination field to blb::move. // will not pass the destination field to blb::move.
record_param* rpb = NULL; jrd_rel* relation = nullptr;
Record* record = nullptr;
USHORT fieldId = 0; USHORT fieldId = 0;
if (to) if (to)
{ {
const FieldNode* toField = nodeAs<FieldNode>(to); const FieldNode* toField = nodeAs<FieldNode>(to);
if (toField) if (toField)
{ {
const auto rpb = &request->req_rpb[toField->fieldStream];
relation = rpb->rpb_relation;
record = rpb->rpb_record;
fieldId = toField->fieldId; fieldId = toField->fieldId;
rpb = &request->req_rpb[toField->fieldStream];
} }
else if (!(nodeAs<ParameterNode>(to) || nodeAs<VariableNode>(to))) else if (!(nodeAs<ParameterNode>(to) || nodeAs<VariableNode>(to)))
BUGCHECK(199); // msg 199 expected field node BUGCHECK(199); // msg 199 expected field node
} }
blb::move(tdbb, from_desc, to_desc, rpb, fieldId); blb::move(tdbb, from_desc, to_desc, relation, record, fieldId);
} }
else if (!DSC_EQUIV(from_desc, to_desc, false)) else if (!DSC_EQUIV(from_desc, to_desc, false))
{ {

View File

@ -432,7 +432,8 @@ void SortedStream::mapData(thread_db* tdbb, jrd_req* request, UCHAR* data) const
const auto relation = rpb->rpb_relation; const auto relation = rpb->rpb_relation;
// Ensure the record is still in the most recent format // Ensure the record is still in the most recent format
VIO_record(tdbb, rpb, MET_current(tdbb, relation), tdbb->getDefaultPool()); const auto record =
VIO_record(tdbb, rpb, MET_current(tdbb, relation), tdbb->getDefaultPool());
// Set all fields to NULL if the stream was originally marked as invalid // Set all fields to NULL if the stream was originally marked as invalid
if (!rpb->rpb_number.isValid()) if (!rpb->rpb_number.isValid())
@ -456,7 +457,7 @@ void SortedStream::mapData(thread_db* tdbb, jrd_req* request, UCHAR* data) const
auto temp = *rpb; auto temp = *rpb;
temp.rpb_record = nullptr; temp.rpb_record = nullptr;
AutoPtr<Record> cleanupRecord; AutoPtr<Record> tempRecord;
// If the primary record version disappeared, we cannot proceed // If the primary record version disappeared, we cannot proceed
@ -470,9 +471,9 @@ void SortedStream::mapData(thread_db* tdbb, jrd_req* request, UCHAR* data) const
if (!(temp.rpb_runtime_flags & RPB_undo_data)) if (!(temp.rpb_runtime_flags & RPB_undo_data))
VIO_data(tdbb, &temp, tdbb->getDefaultPool()); VIO_data(tdbb, &temp, tdbb->getDefaultPool());
cleanupRecord = temp.rpb_record; tempRecord = temp.rpb_record;
VIO_copy_record(tdbb, &temp, rpb); VIO_copy_record(tdbb, relation, tempRecord, record);
if (temp.rpb_transaction_nr == orgTraNum && orgTraNum != selfTraNum) if (temp.rpb_transaction_nr == orgTraNum && orgTraNum != selfTraNum)
continue; // we surely see the original record version continue; // we surely see the original record version
@ -588,11 +589,11 @@ void SortedStream::mapData(thread_db* tdbb, jrd_req* request, UCHAR* data) const
VIO_data(tdbb, &temp, tdbb->getDefaultPool()); VIO_data(tdbb, &temp, tdbb->getDefaultPool());
cleanupRecord.reset(temp.rpb_record); tempRecord.reset(temp.rpb_record);
++backversions; ++backversions;
} }
VIO_copy_record(tdbb, &temp, rpb); VIO_copy_record(tdbb, relation, tempRecord, record);
} }
} }

View File

@ -1252,7 +1252,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb,
} }
void VIO_copy_record(thread_db* tdbb, record_param* org_rpb, record_param* new_rpb) void VIO_copy_record(thread_db* tdbb, jrd_rel* relation, Record* orgRecord, Record* newRecord)
{ {
/************************************** /**************************************
* *
@ -1264,60 +1264,60 @@ void VIO_copy_record(thread_db* tdbb, record_param* org_rpb, record_param* new_r
* Copy the given record to a new destination, * Copy the given record to a new destination,
* taking care about possible format differences. * taking care about possible format differences.
**************************************/ **************************************/
fb_assert(org_rpb && new_rpb);
Record* const org_record = org_rpb->rpb_record;
Record* const new_record = new_rpb->rpb_record;
fb_assert(org_record && new_record);
// dimitr: Clear the req_null flag that may stay active after the last // dimitr: Clear the req_null flag that may stay active after the last
// boolean evaluation. Here we use only EVL_field() calls that // boolean evaluation. Here we use only EVL_field() calls that
// do not touch this flag and data copying is done only for // do not touch this flag and data copying is done only for
// non-NULL fields, so req_null should never be seen inside blb::move(). // non-NULL fields, so req_null should never be seen inside blb::move().
// See CORE-6090 for details. // See CORE-6090 for details.
jrd_req* const request = tdbb->getRequest(); const auto request = tdbb->getRequest();
request->req_flags &= ~req_null; request->req_flags &= ~req_null;
const auto orgFormat = orgRecord->getFormat();
const auto newFormat = newRecord->getFormat();
fb_assert(orgFormat && newFormat);
// Copy the original record to the new record. If the format hasn't changed, // Copy the original record to the new record. If the format hasn't changed,
// this is a simple move. If the format has changed, each field must be // this is a simple move. If the format has changed, each field must be
// fetched and moved separately, remembering to set the missing flag. // fetched and moved separately, remembering to set the missing flag.
if (new_rpb->rpb_format_number == org_rpb->rpb_format_number) if (newFormat->fmt_version == orgFormat->fmt_version)
new_record->copyDataFrom(org_record, true);
else
{ {
DSC org_desc, new_desc; newRecord->copyDataFrom(orgRecord, true);
return;
}
for (USHORT i = 0; i < new_record->getFormat()->fmt_count; i++) dsc orgDesc, newDesc;
for (USHORT i = 0; i < newFormat->fmt_count; i++)
{
newRecord->clearNull(i);
if (EVL_field(relation, newRecord, i, &newDesc))
{ {
new_record->clearNull(i); if (EVL_field(relation, orgRecord, i, &orgDesc))
if (EVL_field(new_rpb->rpb_relation, new_record, i, &new_desc))
{ {
if (EVL_field(org_rpb->rpb_relation, org_record, i, &org_desc)) // If the source is not a blob or it's a temporary blob,
{ // then we'll need to materialize the resulting blob.
// If the source is not a blob or it's a temporary blob, // Thus blb::move() is called with rpb and field ID.
// then we'll need to materialize the resulting blob. // See also CORE-5600.
// Thus blb::move() is called with rpb and field ID.
// See also CORE-5600.
const bool materialize = const bool materialize =
(DTYPE_IS_BLOB_OR_QUAD(new_desc.dsc_dtype) && (DTYPE_IS_BLOB_OR_QUAD(newDesc.dsc_dtype) &&
!(DTYPE_IS_BLOB_OR_QUAD(org_desc.dsc_dtype) && !(DTYPE_IS_BLOB_OR_QUAD(orgDesc.dsc_dtype) &&
((bid*) org_desc.dsc_address)->bid_internal.bid_relation_id)); ((bid*) orgDesc.dsc_address)->bid_internal.bid_relation_id));
if (materialize) if (materialize)
blb::move(tdbb, &org_desc, &new_desc, new_rpb, i); blb::move(tdbb, &orgDesc, &newDesc, relation, newRecord, i);
else
MOV_move(tdbb, &org_desc, &new_desc);
}
else else
{ MOV_move(tdbb, &orgDesc, &newDesc);
new_record->setNull(i); }
else
{
newRecord->setNull(i);
if (new_desc.dsc_dtype) if (!newDesc.isUnknown())
memset(new_desc.dsc_address, 0, new_desc.dsc_length); memset(newDesc.dsc_address, 0, newDesc.dsc_length);
}
} }
} }
} }
@ -4038,9 +4038,10 @@ bool VIO_writelock(thread_db* tdbb, record_param* org_rpb, jrd_tra* transaction)
transaction->tra_flags |= TRA_write; transaction->tra_flags |= TRA_write;
if (!org_rpb->rpb_record) Record* org_record = org_rpb->rpb_record;
if (!org_record)
{ {
Record* const org_record = VIO_record(tdbb, org_rpb, NULL, tdbb->getDefaultPool()); org_record = VIO_record(tdbb, org_rpb, NULL, tdbb->getDefaultPool());
org_rpb->rpb_address = org_record->getData(); org_rpb->rpb_address = org_record->getData();
const Format* const org_format = org_record->getFormat(); const Format* const org_format = org_record->getFormat();
org_rpb->rpb_length = org_format->fmt_length; org_rpb->rpb_length = org_format->fmt_length;
@ -4066,7 +4067,7 @@ bool VIO_writelock(thread_db* tdbb, record_param* org_rpb, jrd_tra* transaction)
new_rpb.rpb_length = new_format->fmt_length; new_rpb.rpb_length = new_format->fmt_length;
new_rpb.rpb_format_number = new_format->fmt_version; new_rpb.rpb_format_number = new_format->fmt_version;
VIO_copy_record(tdbb, org_rpb, &new_rpb); VIO_copy_record(tdbb, relation, org_record, new_record);
} }
// We're about to lock the record. Post a refetch request // We're about to lock the record. Post a refetch request

View File

@ -40,7 +40,7 @@ namespace Jrd {
void VIO_backout(Jrd::thread_db*, Jrd::record_param*, const Jrd::jrd_tra*); void VIO_backout(Jrd::thread_db*, Jrd::record_param*, const Jrd::jrd_tra*);
bool VIO_chase_record_version(Jrd::thread_db*, Jrd::record_param*, bool VIO_chase_record_version(Jrd::thread_db*, Jrd::record_param*,
Jrd::jrd_tra*, MemoryPool*, bool, bool); Jrd::jrd_tra*, MemoryPool*, bool, bool);
void VIO_copy_record(Jrd::thread_db*, Jrd::record_param*, Jrd::record_param*); void VIO_copy_record(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::Record*, Jrd::Record*);
void VIO_data(Jrd::thread_db*, Jrd::record_param*, MemoryPool*); void VIO_data(Jrd::thread_db*, Jrd::record_param*, MemoryPool*);
bool VIO_erase(Jrd::thread_db*, Jrd::record_param*, Jrd::jrd_tra*); bool VIO_erase(Jrd::thread_db*, Jrd::record_param*, Jrd::jrd_tra*);
void VIO_fini(Jrd::thread_db*); void VIO_fini(Jrd::thread_db*);