mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-02-02 10:40:38 +01:00
Improvement #8042 : Improve conflict resolution on replica when table have both Primary and Unique keys
This commit is contained in:
parent
eb3a0d3609
commit
62f4c5a786
@ -201,11 +201,12 @@ namespace
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class LocalThreadContext
|
class LocalThreadContext : Firebird::ContextPoolHolder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LocalThreadContext(thread_db* tdbb, jrd_tra* tra, Request* req = NULL)
|
LocalThreadContext(thread_db* tdbb, jrd_tra* tra, Request* req = NULL)
|
||||||
: m_tdbb(tdbb)
|
: Firebird::ContextPoolHolder(req ? req->req_pool : tdbb->getDefaultPool()),
|
||||||
|
m_tdbb(tdbb)
|
||||||
{
|
{
|
||||||
tdbb->setTransaction(tra);
|
tdbb->setTransaction(tra);
|
||||||
tdbb->setRequest(req);
|
tdbb->setRequest(req);
|
||||||
@ -572,6 +573,8 @@ void Applier::insertRecord(thread_db* tdbb, TraNumber traNum,
|
|||||||
rpb.rpb_length = length;
|
rpb.rpb_length = length;
|
||||||
record->copyDataFrom(data);
|
record->copyDataFrom(data);
|
||||||
|
|
||||||
|
FbLocalStatus error;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
doInsert(tdbb, &rpb, transaction);
|
doInsert(tdbb, &rpb, transaction);
|
||||||
@ -586,6 +589,7 @@ void Applier::insertRecord(thread_db* tdbb, TraNumber traNum,
|
|||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ex.stuffException(&error);
|
||||||
fb_utils::init_status(tdbb->tdbb_status_vector);
|
fb_utils::init_status(tdbb->tdbb_status_vector);
|
||||||
|
|
||||||
// The subsequent backout will delete the blobs we have stored before,
|
// The subsequent backout will delete the blobs we have stored before,
|
||||||
@ -626,8 +630,14 @@ void Applier::insertRecord(thread_db* tdbb, TraNumber traNum,
|
|||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
#ifdef RESOLVE_CONFLICTS
|
#ifdef RESOLVE_CONFLICTS
|
||||||
|
fb_assert(error[1] == isc_unique_key_violation || error[1] == isc_no_dup);
|
||||||
|
fb_assert(error[2] == isc_arg_string);
|
||||||
|
fb_assert(error[3] != 0);
|
||||||
|
|
||||||
|
const char* idxName = reinterpret_cast<const char*>(error[3]);
|
||||||
|
|
||||||
index_desc idx;
|
index_desc idx;
|
||||||
const auto indexed = lookupRecord(tdbb, relation, record, idx);
|
const auto indexed = lookupRecord(tdbb, relation, record, idx, idxName);
|
||||||
|
|
||||||
AutoPtr<Record> cleanup;
|
AutoPtr<Record> cleanup;
|
||||||
|
|
||||||
@ -1076,7 +1086,7 @@ bool Applier::compareKey(thread_db* tdbb, jrd_rel* relation, const index_desc& i
|
|||||||
|
|
||||||
bool Applier::lookupRecord(thread_db* tdbb,
|
bool Applier::lookupRecord(thread_db* tdbb,
|
||||||
jrd_rel* relation, Record* record,
|
jrd_rel* relation, Record* record,
|
||||||
index_desc& idx)
|
index_desc& idx, const char* idxName)
|
||||||
{
|
{
|
||||||
RecordBitmap::reset(m_bitmap);
|
RecordBitmap::reset(m_bitmap);
|
||||||
|
|
||||||
@ -1087,7 +1097,24 @@ bool Applier::lookupRecord(thread_db* tdbb,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lookupKey(tdbb, relation, idx))
|
bool haveIdx = false;
|
||||||
|
if (idxName)
|
||||||
|
{
|
||||||
|
SLONG foundRelId;
|
||||||
|
IndexStatus idxStatus;
|
||||||
|
SLONG idx_id = MET_lookup_index_name(tdbb, idxName, &foundRelId, &idxStatus);
|
||||||
|
|
||||||
|
fb_assert(idxStatus == MET_object_active);
|
||||||
|
fb_assert(foundRelId == relation->rel_id);
|
||||||
|
|
||||||
|
haveIdx = (idxStatus == MET_object_active) && (foundRelId == relation->rel_id) &&
|
||||||
|
BTR_lookup(tdbb, relation, idx_id, &idx, relation->getPages(tdbb));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!haveIdx)
|
||||||
|
haveIdx = lookupKey(tdbb, relation, idx);
|
||||||
|
|
||||||
|
if (haveIdx)
|
||||||
{
|
{
|
||||||
IndexKey key(tdbb, relation, &idx);
|
IndexKey key(tdbb, relation, &idx);
|
||||||
if (const auto result = key.compose(record))
|
if (const auto result = key.compose(record))
|
||||||
|
@ -190,7 +190,7 @@ namespace Jrd
|
|||||||
const index_desc& idx,
|
const index_desc& idx,
|
||||||
Record* record1, Record* record2);
|
Record* record1, Record* record2);
|
||||||
bool lookupRecord(thread_db* tdbb, jrd_rel* relation,
|
bool lookupRecord(thread_db* tdbb, jrd_rel* relation,
|
||||||
Record* record, index_desc& idx);
|
Record* record, index_desc& idx, const char* idxName = nullptr);
|
||||||
|
|
||||||
const Format* findFormat(thread_db* tdbb, jrd_rel* relation, ULONG length);
|
const Format* findFormat(thread_db* tdbb, jrd_rel* relation, ULONG length);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user